1# sql/selectable.py 
    2# Copyright (C) 2005-2025 the SQLAlchemy authors and contributors 
    3# <see AUTHORS file> 
    4# 
    5# This module is part of SQLAlchemy and is released under 
    6# the MIT License: https://www.opensource.org/licenses/mit-license.php 
    7 
    8"""The :class:`_expression.FromClause` class of SQL expression elements, 
    9representing 
    10SQL tables and derived rowsets. 
    11 
    12""" 
    13 
    14from __future__ import annotations 
    15 
    16import collections 
    17from enum import Enum 
    18import itertools 
    19from typing import AbstractSet 
    20from typing import Any as TODO_Any 
    21from typing import Any 
    22from typing import Callable 
    23from typing import cast 
    24from typing import Dict 
    25from typing import Generic 
    26from typing import Iterable 
    27from typing import Iterator 
    28from typing import List 
    29from typing import Literal 
    30from typing import NamedTuple 
    31from typing import NoReturn 
    32from typing import Optional 
    33from typing import overload 
    34from typing import Protocol 
    35from typing import Sequence 
    36from typing import Set 
    37from typing import Tuple 
    38from typing import Type 
    39from typing import TYPE_CHECKING 
    40from typing import TypeVar 
    41from typing import Union 
    42 
    43from . import cache_key 
    44from . import coercions 
    45from . import operators 
    46from . import roles 
    47from . import traversals 
    48from . import type_api 
    49from . import visitors 
    50from ._typing import _ColumnsClauseArgument 
    51from ._typing import _no_kw 
    52from ._typing import _T 
    53from ._typing import _Ts 
    54from ._typing import is_column_element 
    55from ._typing import is_select_statement 
    56from ._typing import is_subquery 
    57from ._typing import is_table 
    58from ._typing import is_text_clause 
    59from .annotation import Annotated 
    60from .annotation import SupportsCloneAnnotations 
    61from .base import _clone 
    62from .base import _cloned_difference 
    63from .base import _cloned_intersection 
    64from .base import _entity_namespace_key 
    65from .base import _EntityNamespace 
    66from .base import _expand_cloned 
    67from .base import _from_objects 
    68from .base import _generative 
    69from .base import _never_select_column 
    70from .base import _NoArg 
    71from .base import _select_iterables 
    72from .base import CacheableOptions 
    73from .base import ColumnCollection 
    74from .base import ColumnSet 
    75from .base import CompileState 
    76from .base import DedupeColumnCollection 
    77from .base import DialectKWArgs 
    78from .base import Executable 
    79from .base import Generative 
    80from .base import HasCompileState 
    81from .base import HasMemoized 
    82from .base import HasSyntaxExtensions 
    83from .base import Immutable 
    84from .base import SyntaxExtension 
    85from .coercions import _document_text_coercion 
    86from .elements import _anonymous_label 
    87from .elements import BindParameter 
    88from .elements import BooleanClauseList 
    89from .elements import ClauseElement 
    90from .elements import ClauseList 
    91from .elements import ColumnClause 
    92from .elements import ColumnElement 
    93from .elements import DQLDMLClauseElement 
    94from .elements import GroupedElement 
    95from .elements import literal_column 
    96from .elements import TableValuedColumn 
    97from .elements import UnaryExpression 
    98from .operators import OperatorType 
    99from .sqltypes import NULLTYPE 
    100from .visitors import _TraverseInternalsType 
    101from .visitors import InternalTraversal 
    102from .visitors import prefix_anon_map 
    103from .. import exc 
    104from .. import util 
    105from ..util import HasMemoized_ro_memoized_attribute 
    106from ..util import warn_deprecated 
    107from ..util.typing import Self 
    108from ..util.typing import TupleAny 
    109from ..util.typing import Unpack 
    110 
    111 
    112and_ = BooleanClauseList.and_ 
    113 
    114 
    115if TYPE_CHECKING: 
    116    from ._typing import _ColumnExpressionArgument 
    117    from ._typing import _ColumnExpressionOrStrLabelArgument 
    118    from ._typing import _FromClauseArgument 
    119    from ._typing import _JoinTargetArgument 
    120    from ._typing import _LimitOffsetType 
    121    from ._typing import _MAYBE_ENTITY 
    122    from ._typing import _NOT_ENTITY 
    123    from ._typing import _OnClauseArgument 
    124    from ._typing import _SelectStatementForCompoundArgument 
    125    from ._typing import _T0 
    126    from ._typing import _T1 
    127    from ._typing import _T2 
    128    from ._typing import _T3 
    129    from ._typing import _T4 
    130    from ._typing import _T5 
    131    from ._typing import _T6 
    132    from ._typing import _T7 
    133    from ._typing import _TextCoercedExpressionArgument 
    134    from ._typing import _TypedColumnClauseArgument as _TCCA 
    135    from ._typing import _TypeEngineArgument 
    136    from .base import _AmbiguousTableNameMap 
    137    from .base import ExecutableOption 
    138    from .base import ReadOnlyColumnCollection 
    139    from .cache_key import _CacheKeyTraversalType 
    140    from .compiler import SQLCompiler 
    141    from .ddl import CreateTableAs 
    142    from .dml import Delete 
    143    from .dml import Update 
    144    from .elements import BinaryExpression 
    145    from .elements import KeyedColumnElement 
    146    from .elements import Label 
    147    from .elements import NamedColumn 
    148    from .elements import TextClause 
    149    from .functions import Function 
    150    from .schema import ForeignKey 
    151    from .schema import ForeignKeyConstraint 
    152    from .schema import MetaData 
    153    from .sqltypes import TableValueType 
    154    from .type_api import TypeEngine 
    155    from .visitors import _CloneCallableType 
    156 
    157 
    158_ColumnsClauseElement = Union["FromClause", ColumnElement[Any], "TextClause"] 
    159_LabelConventionCallable = Callable[ 
    160    [Union["ColumnElement[Any]", "TextClause"]], Optional[str] 
    161] 
    162 
    163 
    164class _JoinTargetProtocol(Protocol): 
    165    @util.ro_non_memoized_property 
    166    def _from_objects(self) -> List[FromClause]: ... 
    167 
    168    @util.ro_non_memoized_property 
    169    def entity_namespace(self) -> _EntityNamespace: ... 
    170 
    171 
    172_JoinTargetElement = Union["FromClause", _JoinTargetProtocol] 
    173_OnClauseElement = Union["ColumnElement[bool]", _JoinTargetProtocol] 
    174 
    175_ForUpdateOfArgument = Union[ 
    176    # single column, Table, ORM Entity 
    177    Union[ 
    178        "_ColumnExpressionArgument[Any]", 
    179        "_FromClauseArgument", 
    180    ], 
    181    # or sequence of single column elements 
    182    Sequence["_ColumnExpressionArgument[Any]"], 
    183] 
    184 
    185 
    186_SetupJoinsElement = Tuple[ 
    187    _JoinTargetElement, 
    188    Optional[_OnClauseElement], 
    189    Optional["FromClause"], 
    190    Dict[str, Any], 
    191] 
    192 
    193 
    194_SelectIterable = Iterable[Union["ColumnElement[Any]", "TextClause"]] 
    195 
    196 
    197class _OffsetLimitParam(BindParameter[int]): 
    198    inherit_cache = True 
    199 
    200    @property 
    201    def _limit_offset_value(self) -> Optional[int]: 
    202        return self.effective_value 
    203 
    204 
    205class ReturnsRows(roles.ReturnsRowsRole, DQLDMLClauseElement): 
    206    """The base-most class for Core constructs that have some concept of 
    207    columns that can represent rows. 
    208 
    209    While the SELECT statement and TABLE are the primary things we think 
    210    of in this category,  DML like INSERT, UPDATE and DELETE can also specify 
    211    RETURNING which means they can be used in CTEs and other forms, and 
    212    PostgreSQL has functions that return rows also. 
    213 
    214    .. versionadded:: 1.4 
    215 
    216    """ 
    217 
    218    _is_returns_rows = True 
    219 
    220    # sub-elements of returns_rows 
    221    _is_from_clause = False 
    222    _is_select_base = False 
    223    _is_select_statement = False 
    224    _is_lateral = False 
    225 
    226    @property 
    227    def selectable(self) -> ReturnsRows: 
    228        return self 
    229 
    230    @util.ro_non_memoized_property 
    231    def _all_selected_columns(self) -> _SelectIterable: 
    232        """A sequence of column expression objects that represents the 
    233        "selected" columns of this :class:`_expression.ReturnsRows`. 
    234 
    235        This is typically equivalent to .exported_columns except it is 
    236        delivered in the form of a straight sequence and not  keyed 
    237        :class:`_expression.ColumnCollection`. 
    238 
    239        """ 
    240        raise NotImplementedError() 
    241 
    242    def is_derived_from(self, fromclause: Optional[FromClause]) -> bool: 
    243        """Return ``True`` if this :class:`.ReturnsRows` is 
    244        'derived' from the given :class:`.FromClause`. 
    245 
    246        An example would be an Alias of a Table is derived from that Table. 
    247 
    248        """ 
    249        raise NotImplementedError() 
    250 
    251    def _generate_fromclause_column_proxies( 
    252        self, 
    253        fromclause: FromClause, 
    254        columns: ColumnCollection[str, KeyedColumnElement[Any]], 
    255        primary_key: ColumnSet, 
    256        foreign_keys: Set[KeyedColumnElement[Any]], 
    257    ) -> None: 
    258        """Populate columns into an :class:`.AliasedReturnsRows` object.""" 
    259 
    260        raise NotImplementedError() 
    261 
    262    def _refresh_for_new_column(self, column: ColumnElement[Any]) -> None: 
    263        """reset internal collections for an incoming column being added.""" 
    264        raise NotImplementedError() 
    265 
    266    @property 
    267    def exported_columns(self) -> ReadOnlyColumnCollection[Any, Any]: 
    268        """A :class:`_expression.ColumnCollection` 
    269        that represents the "exported" 
    270        columns of this :class:`_expression.ReturnsRows`. 
    271 
    272        The "exported" columns represent the collection of 
    273        :class:`_expression.ColumnElement` 
    274        expressions that are rendered by this SQL 
    275        construct.   There are primary varieties which are the 
    276        "FROM clause columns" of a FROM clause, such as a table, join, 
    277        or subquery, the "SELECTed columns", which are the columns in 
    278        the "columns clause" of a SELECT statement, and the RETURNING 
    279        columns in a DML statement.. 
    280 
    281        .. versionadded:: 1.4 
    282 
    283        .. seealso:: 
    284 
    285            :attr:`_expression.FromClause.exported_columns` 
    286 
    287            :attr:`_expression.SelectBase.exported_columns` 
    288        """ 
    289 
    290        raise NotImplementedError() 
    291 
    292 
    293class ExecutableReturnsRows(Executable, ReturnsRows): 
    294    """base for executable statements that return rows.""" 
    295 
    296 
    297class TypedReturnsRows(ExecutableReturnsRows, Generic[Unpack[_Ts]]): 
    298    """base for a typed executable statements that return rows.""" 
    299 
    300 
    301class Selectable(ReturnsRows): 
    302    """Mark a class as being selectable.""" 
    303 
    304    __visit_name__ = "selectable" 
    305 
    306    is_selectable = True 
    307 
    308    def _refresh_for_new_column(self, column: ColumnElement[Any]) -> None: 
    309        raise NotImplementedError() 
    310 
    311    def lateral(self, name: Optional[str] = None) -> LateralFromClause: 
    312        """Return a LATERAL alias of this :class:`_expression.Selectable`. 
    313 
    314        The return value is the :class:`_expression.Lateral` construct also 
    315        provided by the top-level :func:`_expression.lateral` function. 
    316 
    317        .. seealso:: 
    318 
    319            :ref:`tutorial_lateral_correlation` -  overview of usage. 
    320 
    321        """ 
    322        return Lateral._construct(self, name=name) 
    323 
    324    @util.deprecated( 
    325        "1.4", 
    326        message="The :meth:`.Selectable.replace_selectable` method is " 
    327        "deprecated, and will be removed in a future release.  Similar " 
    328        "functionality is available via the sqlalchemy.sql.visitors module.", 
    329    ) 
    330    @util.preload_module("sqlalchemy.sql.util") 
    331    def replace_selectable(self, old: FromClause, alias: Alias) -> Self: 
    332        """Replace all occurrences of :class:`_expression.FromClause` 
    333        'old' with the given :class:`_expression.Alias` 
    334        object, returning a copy of this :class:`_expression.FromClause`. 
    335 
    336        """ 
    337        return util.preloaded.sql_util.ClauseAdapter(alias).traverse(self) 
    338 
    339    def corresponding_column( 
    340        self, column: KeyedColumnElement[Any], require_embedded: bool = False 
    341    ) -> Optional[KeyedColumnElement[Any]]: 
    342        """Given a :class:`_expression.ColumnElement`, return the exported 
    343        :class:`_expression.ColumnElement` object from the 
    344        :attr:`_expression.Selectable.exported_columns` 
    345        collection of this :class:`_expression.Selectable` 
    346        which corresponds to that 
    347        original :class:`_expression.ColumnElement` via a common ancestor 
    348        column. 
    349 
    350        :param column: the target :class:`_expression.ColumnElement` 
    351                      to be matched. 
    352 
    353        :param require_embedded: only return corresponding columns for 
    354         the given :class:`_expression.ColumnElement`, if the given 
    355         :class:`_expression.ColumnElement` 
    356         is actually present within a sub-element 
    357         of this :class:`_expression.Selectable`. 
    358         Normally the column will match if 
    359         it merely shares a common ancestor with one of the exported 
    360         columns of this :class:`_expression.Selectable`. 
    361 
    362        .. seealso:: 
    363 
    364            :attr:`_expression.Selectable.exported_columns` - the 
    365            :class:`_expression.ColumnCollection` 
    366            that is used for the operation. 
    367 
    368            :meth:`_expression.ColumnCollection.corresponding_column` 
    369            - implementation 
    370            method. 
    371 
    372        """ 
    373 
    374        return self.exported_columns.corresponding_column( 
    375            column, require_embedded 
    376        ) 
    377 
    378 
    379class HasPrefixes: 
    380    _prefixes: Tuple[Tuple[DQLDMLClauseElement, str], ...] = () 
    381 
    382    _has_prefixes_traverse_internals: _TraverseInternalsType = [ 
    383        ("_prefixes", InternalTraversal.dp_prefix_sequence) 
    384    ] 
    385 
    386    @_generative 
    387    @_document_text_coercion( 
    388        "prefixes", 
    389        ":meth:`_expression.HasPrefixes.prefix_with`", 
    390        ":paramref:`.HasPrefixes.prefix_with.*prefixes`", 
    391    ) 
    392    def prefix_with( 
    393        self, 
    394        *prefixes: _TextCoercedExpressionArgument[Any], 
    395        dialect: str = "*", 
    396    ) -> Self: 
    397        r"""Add one or more expressions following the statement keyword, i.e. 
    398        SELECT, INSERT, UPDATE, or DELETE. Generative. 
    399 
    400        This is used to support backend-specific prefix keywords such as those 
    401        provided by MySQL. 
    402 
    403        E.g.:: 
    404 
    405            stmt = table.insert().prefix_with("LOW_PRIORITY", dialect="mysql") 
    406 
    407            # MySQL 5.7 optimizer hints 
    408            stmt = select(table).prefix_with("/*+ BKA(t1) */", dialect="mysql") 
    409 
    410        Multiple prefixes can be specified by multiple calls 
    411        to :meth:`_expression.HasPrefixes.prefix_with`. 
    412 
    413        :param \*prefixes: textual or :class:`_expression.ClauseElement` 
    414         construct which 
    415         will be rendered following the INSERT, UPDATE, or DELETE 
    416         keyword. 
    417        :param dialect: optional string dialect name which will 
    418         limit rendering of this prefix to only that dialect. 
    419 
    420        """ 
    421        self._prefixes = self._prefixes + tuple( 
    422            [ 
    423                (coercions.expect(roles.StatementOptionRole, p), dialect) 
    424                for p in prefixes 
    425            ] 
    426        ) 
    427        return self 
    428 
    429 
    430class HasSuffixes: 
    431    _suffixes: Tuple[Tuple[DQLDMLClauseElement, str], ...] = () 
    432 
    433    _has_suffixes_traverse_internals: _TraverseInternalsType = [ 
    434        ("_suffixes", InternalTraversal.dp_prefix_sequence) 
    435    ] 
    436 
    437    @_generative 
    438    @_document_text_coercion( 
    439        "suffixes", 
    440        ":meth:`_expression.HasSuffixes.suffix_with`", 
    441        ":paramref:`.HasSuffixes.suffix_with.*suffixes`", 
    442    ) 
    443    def suffix_with( 
    444        self, 
    445        *suffixes: _TextCoercedExpressionArgument[Any], 
    446        dialect: str = "*", 
    447    ) -> Self: 
    448        r"""Add one or more expressions following the statement as a whole. 
    449 
    450        This is used to support backend-specific suffix keywords on 
    451        certain constructs. 
    452 
    453        E.g.:: 
    454 
    455            stmt = ( 
    456                select(col1, col2) 
    457                .cte() 
    458                .suffix_with( 
    459                    "cycle empno set y_cycle to 1 default 0", dialect="oracle" 
    460                ) 
    461            ) 
    462 
    463        Multiple suffixes can be specified by multiple calls 
    464        to :meth:`_expression.HasSuffixes.suffix_with`. 
    465 
    466        :param \*suffixes: textual or :class:`_expression.ClauseElement` 
    467         construct which 
    468         will be rendered following the target clause. 
    469        :param dialect: Optional string dialect name which will 
    470         limit rendering of this suffix to only that dialect. 
    471 
    472        """ 
    473        self._suffixes = self._suffixes + tuple( 
    474            [ 
    475                (coercions.expect(roles.StatementOptionRole, p), dialect) 
    476                for p in suffixes 
    477            ] 
    478        ) 
    479        return self 
    480 
    481 
    482class HasHints: 
    483    _hints: util.immutabledict[Tuple[FromClause, str], str] = ( 
    484        util.immutabledict() 
    485    ) 
    486    _statement_hints: Tuple[Tuple[str, str], ...] = () 
    487 
    488    _has_hints_traverse_internals: _TraverseInternalsType = [ 
    489        ("_statement_hints", InternalTraversal.dp_statement_hint_list), 
    490        ("_hints", InternalTraversal.dp_table_hint_list), 
    491    ] 
    492 
    493    @_generative 
    494    def with_statement_hint(self, text: str, dialect_name: str = "*") -> Self: 
    495        """Add a statement hint to this :class:`_expression.Select` or 
    496        other selectable object. 
    497 
    498        .. tip:: 
    499 
    500            :meth:`_expression.Select.with_statement_hint` generally adds hints 
    501            **at the trailing end** of a SELECT statement.  To place 
    502            dialect-specific hints such as optimizer hints at the **front** of 
    503            the SELECT statement after the SELECT keyword, use the 
    504            :meth:`_expression.Select.prefix_with` method for an open-ended 
    505            space, or for table-specific hints the 
    506            :meth:`_expression.Select.with_hint` may be used, which places 
    507            hints in a dialect-specific location. 
    508 
    509        This method is similar to :meth:`_expression.Select.with_hint` except 
    510        that it does not require an individual table, and instead applies to 
    511        the statement as a whole. 
    512 
    513        Hints here are specific to the backend database and may include 
    514        directives such as isolation levels, file directives, fetch directives, 
    515        etc. 
    516 
    517        .. seealso:: 
    518 
    519            :meth:`_expression.Select.with_hint` 
    520 
    521            :meth:`_expression.Select.prefix_with` - generic SELECT prefixing 
    522            which also can suit some database-specific HINT syntaxes such as 
    523            MySQL or Oracle Database optimizer hints 
    524 
    525        """ 
    526        return self._with_hint(None, text, dialect_name) 
    527 
    528    @_generative 
    529    def with_hint( 
    530        self, 
    531        selectable: _FromClauseArgument, 
    532        text: str, 
    533        dialect_name: str = "*", 
    534    ) -> Self: 
    535        r"""Add an indexing or other executional context hint for the given 
    536        selectable to this :class:`_expression.Select` or other selectable 
    537        object. 
    538 
    539        .. tip:: 
    540 
    541            The :meth:`_expression.Select.with_hint` method adds hints that are 
    542            **specific to a single table** to a statement, in a location that 
    543            is **dialect-specific**.  To add generic optimizer hints to the 
    544            **beginning** of a statement ahead of the SELECT keyword such as 
    545            for MySQL or Oracle Database, use the 
    546            :meth:`_expression.Select.prefix_with` method.  To add optimizer 
    547            hints to the **end** of a statement such as for PostgreSQL, use the 
    548            :meth:`_expression.Select.with_statement_hint` method. 
    549 
    550        The text of the hint is rendered in the appropriate 
    551        location for the database backend in use, relative 
    552        to the given :class:`_schema.Table` or :class:`_expression.Alias` 
    553        passed as the 
    554        ``selectable`` argument. The dialect implementation 
    555        typically uses Python string substitution syntax 
    556        with the token ``%(name)s`` to render the name of 
    557        the table or alias. E.g. when using Oracle Database, the 
    558        following:: 
    559 
    560            select(mytable).with_hint(mytable, "index(%(name)s ix_mytable)") 
    561 
    562        Would render SQL as: 
    563 
    564        .. sourcecode:: sql 
    565 
    566            select /*+ index(mytable ix_mytable) */ ... from mytable 
    567 
    568        The ``dialect_name`` option will limit the rendering of a particular 
    569        hint to a particular backend. Such as, to add hints for both Oracle 
    570        Database and MSSql simultaneously:: 
    571 
    572            select(mytable).with_hint( 
    573                mytable, "index(%(name)s ix_mytable)", "oracle" 
    574            ).with_hint(mytable, "WITH INDEX ix_mytable", "mssql") 
    575 
    576        .. seealso:: 
    577 
    578            :meth:`_expression.Select.with_statement_hint` 
    579 
    580            :meth:`_expression.Select.prefix_with` - generic SELECT prefixing 
    581            which also can suit some database-specific HINT syntaxes such as 
    582            MySQL or Oracle Database optimizer hints 
    583 
    584        """ 
    585 
    586        return self._with_hint(selectable, text, dialect_name) 
    587 
    588    def _with_hint( 
    589        self, 
    590        selectable: Optional[_FromClauseArgument], 
    591        text: str, 
    592        dialect_name: str, 
    593    ) -> Self: 
    594        if selectable is None: 
    595            self._statement_hints += ((dialect_name, text),) 
    596        else: 
    597            self._hints = self._hints.union( 
    598                { 
    599                    ( 
    600                        coercions.expect(roles.FromClauseRole, selectable), 
    601                        dialect_name, 
    602                    ): text 
    603                } 
    604            ) 
    605        return self 
    606 
    607 
    608class FromClause(roles.AnonymizedFromClauseRole, Selectable): 
    609    """Represent an element that can be used within the ``FROM`` 
    610    clause of a ``SELECT`` statement. 
    611 
    612    The most common forms of :class:`_expression.FromClause` are the 
    613    :class:`_schema.Table` and the :func:`_expression.select` constructs.  Key 
    614    features common to all :class:`_expression.FromClause` objects include: 
    615 
    616    * a :attr:`.c` collection, which provides per-name access to a collection 
    617      of :class:`_expression.ColumnElement` objects. 
    618    * a :attr:`.primary_key` attribute, which is a collection of all those 
    619      :class:`_expression.ColumnElement` 
    620      objects that indicate the ``primary_key`` flag. 
    621    * Methods to generate various derivations of a "from" clause, including 
    622      :meth:`_expression.FromClause.alias`, 
    623      :meth:`_expression.FromClause.join`, 
    624      :meth:`_expression.FromClause.select`. 
    625 
    626 
    627    """ 
    628 
    629    __visit_name__ = "fromclause" 
    630    named_with_column = False 
    631 
    632    @util.ro_non_memoized_property 
    633    def _hide_froms(self) -> Iterable[FromClause]: 
    634        return () 
    635 
    636    _is_clone_of: Optional[FromClause] 
    637 
    638    _columns: ColumnCollection[Any, Any] 
    639 
    640    schema: Optional[str] = None 
    641    """Define the 'schema' attribute for this :class:`_expression.FromClause`. 
    642 
    643    This is typically ``None`` for most objects except that of 
    644    :class:`_schema.Table`, where it is taken as the value of the 
    645    :paramref:`_schema.Table.schema` argument. 
    646 
    647    """ 
    648 
    649    is_selectable = True 
    650    _is_from_clause = True 
    651    _is_join = False 
    652 
    653    _use_schema_map = False 
    654 
    655    def select(self) -> Select[Unpack[TupleAny]]: 
    656        r"""Return a SELECT of this :class:`_expression.FromClause`. 
    657 
    658 
    659        e.g.:: 
    660 
    661            stmt = some_table.select().where(some_table.c.id == 5) 
    662 
    663        .. seealso:: 
    664 
    665            :func:`_expression.select` - general purpose 
    666            method which allows for arbitrary column lists. 
    667 
    668        """ 
    669        return Select(self) 
    670 
    671    def join( 
    672        self, 
    673        right: _FromClauseArgument, 
    674        onclause: Optional[_ColumnExpressionArgument[bool]] = None, 
    675        isouter: bool = False, 
    676        full: bool = False, 
    677    ) -> Join: 
    678        """Return a :class:`_expression.Join` from this 
    679        :class:`_expression.FromClause` 
    680        to another :class:`FromClause`. 
    681 
    682        E.g.:: 
    683 
    684            from sqlalchemy import join 
    685 
    686            j = user_table.join( 
    687                address_table, user_table.c.id == address_table.c.user_id 
    688            ) 
    689            stmt = select(user_table).select_from(j) 
    690 
    691        would emit SQL along the lines of: 
    692 
    693        .. sourcecode:: sql 
    694 
    695            SELECT user.id, user.name FROM user 
    696            JOIN address ON user.id = address.user_id 
    697 
    698        :param right: the right side of the join; this is any 
    699         :class:`_expression.FromClause` object such as a 
    700         :class:`_schema.Table` object, and 
    701         may also be a selectable-compatible object such as an ORM-mapped 
    702         class. 
    703 
    704        :param onclause: a SQL expression representing the ON clause of the 
    705         join.  If left at ``None``, :meth:`_expression.FromClause.join` 
    706         will attempt to 
    707         join the two tables based on a foreign key relationship. 
    708 
    709        :param isouter: if True, render a LEFT OUTER JOIN, instead of JOIN. 
    710 
    711        :param full: if True, render a FULL OUTER JOIN, instead of LEFT OUTER 
    712         JOIN.  Implies :paramref:`.FromClause.join.isouter`. 
    713 
    714        .. seealso:: 
    715 
    716            :func:`_expression.join` - standalone function 
    717 
    718            :class:`_expression.Join` - the type of object produced 
    719 
    720        """ 
    721 
    722        return Join(self, right, onclause, isouter, full) 
    723 
    724    def outerjoin( 
    725        self, 
    726        right: _FromClauseArgument, 
    727        onclause: Optional[_ColumnExpressionArgument[bool]] = None, 
    728        full: bool = False, 
    729    ) -> Join: 
    730        """Return a :class:`_expression.Join` from this 
    731        :class:`_expression.FromClause` 
    732        to another :class:`FromClause`, with the "isouter" flag set to 
    733        True. 
    734 
    735        E.g.:: 
    736 
    737            from sqlalchemy import outerjoin 
    738 
    739            j = user_table.outerjoin( 
    740                address_table, user_table.c.id == address_table.c.user_id 
    741            ) 
    742 
    743        The above is equivalent to:: 
    744 
    745            j = user_table.join( 
    746                address_table, user_table.c.id == address_table.c.user_id, isouter=True 
    747            ) 
    748 
    749        :param right: the right side of the join; this is any 
    750         :class:`_expression.FromClause` object such as a 
    751         :class:`_schema.Table` object, and 
    752         may also be a selectable-compatible object such as an ORM-mapped 
    753         class. 
    754 
    755        :param onclause: a SQL expression representing the ON clause of the 
    756         join.  If left at ``None``, :meth:`_expression.FromClause.join` 
    757         will attempt to 
    758         join the two tables based on a foreign key relationship. 
    759 
    760        :param full: if True, render a FULL OUTER JOIN, instead of 
    761         LEFT OUTER JOIN. 
    762 
    763        .. seealso:: 
    764 
    765            :meth:`_expression.FromClause.join` 
    766 
    767            :class:`_expression.Join` 
    768 
    769        """  # noqa: E501 
    770 
    771        return Join(self, right, onclause, True, full) 
    772 
    773    def alias( 
    774        self, name: Optional[str] = None, flat: bool = False 
    775    ) -> NamedFromClause: 
    776        """Return an alias of this :class:`_expression.FromClause`. 
    777 
    778        E.g.:: 
    779 
    780            a2 = some_table.alias("a2") 
    781 
    782        The above code creates an :class:`_expression.Alias` 
    783        object which can be used 
    784        as a FROM clause in any SELECT statement. 
    785 
    786        .. seealso:: 
    787 
    788            :ref:`tutorial_using_aliases` 
    789 
    790            :func:`_expression.alias` 
    791 
    792        """ 
    793 
    794        return Alias._construct(self, name=name) 
    795 
    796    def tablesample( 
    797        self, 
    798        sampling: Union[float, Function[Any]], 
    799        name: Optional[str] = None, 
    800        seed: Optional[roles.ExpressionElementRole[Any]] = None, 
    801    ) -> TableSample: 
    802        """Return a TABLESAMPLE alias of this :class:`_expression.FromClause`. 
    803 
    804        The return value is the :class:`_expression.TableSample` 
    805        construct also 
    806        provided by the top-level :func:`_expression.tablesample` function. 
    807 
    808        .. seealso:: 
    809 
    810            :func:`_expression.tablesample` - usage guidelines and parameters 
    811 
    812        """ 
    813        return TableSample._construct( 
    814            self, sampling=sampling, name=name, seed=seed 
    815        ) 
    816 
    817    def is_derived_from(self, fromclause: Optional[FromClause]) -> bool: 
    818        """Return ``True`` if this :class:`_expression.FromClause` is 
    819        'derived' from the given ``FromClause``. 
    820 
    821        An example would be an Alias of a Table is derived from that Table. 
    822 
    823        """ 
    824        # this is essentially an "identity" check in the base class. 
    825        # Other constructs override this to traverse through 
    826        # contained elements. 
    827        return fromclause in self._cloned_set 
    828 
    829    def _is_lexical_equivalent(self, other: FromClause) -> bool: 
    830        """Return ``True`` if this :class:`_expression.FromClause` and 
    831        the other represent the same lexical identity. 
    832 
    833        This tests if either one is a copy of the other, or 
    834        if they are the same via annotation identity. 
    835 
    836        """ 
    837        return bool(self._cloned_set.intersection(other._cloned_set)) 
    838 
    839    @util.ro_non_memoized_property 
    840    def description(self) -> str: 
    841        """A brief description of this :class:`_expression.FromClause`. 
    842 
    843        Used primarily for error message formatting. 
    844 
    845        """ 
    846        return getattr(self, "name", self.__class__.__name__ + " object") 
    847 
    848    def _generate_fromclause_column_proxies( 
    849        self, 
    850        fromclause: FromClause, 
    851        columns: ColumnCollection[str, KeyedColumnElement[Any]], 
    852        primary_key: ColumnSet, 
    853        foreign_keys: Set[KeyedColumnElement[Any]], 
    854    ) -> None: 
    855        columns._populate_separate_keys( 
    856            col._make_proxy( 
    857                fromclause, primary_key=primary_key, foreign_keys=foreign_keys 
    858            ) 
    859            for col in self.c 
    860        ) 
    861 
    862    @util.ro_non_memoized_property 
    863    def exported_columns( 
    864        self, 
    865    ) -> ReadOnlyColumnCollection[str, KeyedColumnElement[Any]]: 
    866        """A :class:`_expression.ColumnCollection` 
    867        that represents the "exported" 
    868        columns of this :class:`_expression.FromClause`. 
    869 
    870        The "exported" columns for a :class:`_expression.FromClause` 
    871        object are synonymous 
    872        with the :attr:`_expression.FromClause.columns` collection. 
    873 
    874        .. versionadded:: 1.4 
    875 
    876        .. seealso:: 
    877 
    878            :attr:`_expression.Selectable.exported_columns` 
    879 
    880            :attr:`_expression.SelectBase.exported_columns` 
    881 
    882 
    883        """ 
    884        return self.c 
    885 
    886    @util.ro_non_memoized_property 
    887    def columns( 
    888        self, 
    889    ) -> ReadOnlyColumnCollection[str, KeyedColumnElement[Any]]: 
    890        """A named-based collection of :class:`_expression.ColumnElement` 
    891        objects maintained by this :class:`_expression.FromClause`. 
    892 
    893        The :attr:`.columns`, or :attr:`.c` collection, is the gateway 
    894        to the construction of SQL expressions using table-bound or 
    895        other selectable-bound columns:: 
    896 
    897            select(mytable).where(mytable.c.somecolumn == 5) 
    898 
    899        :return: a :class:`.ColumnCollection` object. 
    900 
    901        """ 
    902        return self.c 
    903 
    904    @util.ro_memoized_property 
    905    def c(self) -> ReadOnlyColumnCollection[str, KeyedColumnElement[Any]]: 
    906        """ 
    907        A synonym for :attr:`.FromClause.columns` 
    908 
    909        :return: a :class:`.ColumnCollection` 
    910 
    911        """ 
    912        if "_columns" not in self.__dict__: 
    913            self._setup_collections() 
    914        return self._columns.as_readonly() 
    915 
    916    def _setup_collections(self) -> None: 
    917        with util.mini_gil: 
    918            # detect another thread that raced ahead 
    919            if "_columns" in self.__dict__: 
    920                assert "primary_key" in self.__dict__ 
    921                assert "foreign_keys" in self.__dict__ 
    922                return 
    923 
    924            _columns: ColumnCollection[Any, Any] = ColumnCollection() 
    925            primary_key = ColumnSet() 
    926            foreign_keys: Set[KeyedColumnElement[Any]] = set() 
    927 
    928            self._populate_column_collection( 
    929                columns=_columns, 
    930                primary_key=primary_key, 
    931                foreign_keys=foreign_keys, 
    932            ) 
    933 
    934            # assigning these three collections separately is not itself 
    935            # atomic, but greatly reduces the surface for problems 
    936            self._columns = _columns 
    937            self.primary_key = primary_key  # type: ignore 
    938            self.foreign_keys = foreign_keys  # type: ignore 
    939 
    940    @util.ro_non_memoized_property 
    941    def entity_namespace(self) -> _EntityNamespace: 
    942        """Return a namespace used for name-based access in SQL expressions. 
    943 
    944        This is the namespace that is used to resolve "filter_by()" type 
    945        expressions, such as:: 
    946 
    947            stmt.filter_by(address="some address") 
    948 
    949        It defaults to the ``.c`` collection, however internally it can 
    950        be overridden using the "entity_namespace" annotation to deliver 
    951        alternative results. 
    952 
    953        """ 
    954        return self.c 
    955 
    956    @util.ro_memoized_property 
    957    def primary_key(self) -> Iterable[NamedColumn[Any]]: 
    958        """Return the iterable collection of :class:`_schema.Column` objects 
    959        which comprise the primary key of this :class:`_selectable.FromClause`. 
    960 
    961        For a :class:`_schema.Table` object, this collection is represented 
    962        by the :class:`_schema.PrimaryKeyConstraint` which itself is an 
    963        iterable collection of :class:`_schema.Column` objects. 
    964 
    965        """ 
    966        self._setup_collections() 
    967        return self.primary_key 
    968 
    969    @util.ro_memoized_property 
    970    def foreign_keys(self) -> Iterable[ForeignKey]: 
    971        """Return the collection of :class:`_schema.ForeignKey` marker objects 
    972        which this FromClause references. 
    973 
    974        Each :class:`_schema.ForeignKey` is a member of a 
    975        :class:`_schema.Table`-wide 
    976        :class:`_schema.ForeignKeyConstraint`. 
    977 
    978        .. seealso:: 
    979 
    980            :attr:`_schema.Table.foreign_key_constraints` 
    981 
    982        """ 
    983        self._setup_collections() 
    984        return self.foreign_keys 
    985 
    986    def _reset_column_collection(self) -> None: 
    987        """Reset the attributes linked to the ``FromClause.c`` attribute. 
    988 
    989        This collection is separate from all the other memoized things 
    990        as it has shown to be sensitive to being cleared out in situations 
    991        where enclosing code, typically in a replacement traversal scenario, 
    992        has already established strong relationships 
    993        with the exported columns. 
    994 
    995        The collection is cleared for the case where a table is having a 
    996        column added to it as well as within a Join during copy internals. 
    997 
    998        """ 
    999 
    1000        for key in ["_columns", "columns", "c", "primary_key", "foreign_keys"]: 
    1001            self.__dict__.pop(key, None) 
    1002 
    1003    @util.ro_non_memoized_property 
    1004    def _select_iterable(self) -> _SelectIterable: 
    1005        return (c for c in self.c if not _never_select_column(c)) 
    1006 
    1007    @property 
    1008    def _cols_populated(self) -> bool: 
    1009        return "_columns" in self.__dict__ 
    1010 
    1011    def _populate_column_collection( 
    1012        self, 
    1013        columns: ColumnCollection[str, KeyedColumnElement[Any]], 
    1014        primary_key: ColumnSet, 
    1015        foreign_keys: Set[KeyedColumnElement[Any]], 
    1016    ) -> None: 
    1017        """Called on subclasses to establish the .c collection. 
    1018 
    1019        Each implementation has a different way of establishing 
    1020        this collection. 
    1021 
    1022        """ 
    1023 
    1024    def _refresh_for_new_column(self, column: ColumnElement[Any]) -> None: 
    1025        """Given a column added to the .c collection of an underlying 
    1026        selectable, produce the local version of that column, assuming this 
    1027        selectable ultimately should proxy this column. 
    1028 
    1029        this is used to "ping" a derived selectable to add a new column 
    1030        to its .c. collection when a Column has been added to one of the 
    1031        Table objects it ultimately derives from. 
    1032 
    1033        If the given selectable hasn't populated its .c. collection yet, 
    1034        it should at least pass on the message to the contained selectables, 
    1035        but it will return None. 
    1036 
    1037        This method is currently used by Declarative to allow Table 
    1038        columns to be added to a partially constructed inheritance 
    1039        mapping that may have already produced joins.  The method 
    1040        isn't public right now, as the full span of implications 
    1041        and/or caveats aren't yet clear. 
    1042 
    1043        It's also possible that this functionality could be invoked by 
    1044        default via an event, which would require that 
    1045        selectables maintain a weak referencing collection of all 
    1046        derivations. 
    1047 
    1048        """ 
    1049        self._reset_column_collection() 
    1050 
    1051    def _anonymous_fromclause( 
    1052        self, *, name: Optional[str] = None, flat: bool = False 
    1053    ) -> FromClause: 
    1054        return self.alias(name=name) 
    1055 
    1056    if TYPE_CHECKING: 
    1057 
    1058        def self_group( 
    1059            self, against: Optional[OperatorType] = None 
    1060        ) -> Union[FromGrouping, Self]: ... 
    1061 
    1062 
    1063class NamedFromClause(FromClause): 
    1064    """A :class:`.FromClause` that has a name. 
    1065 
    1066    Examples include tables, subqueries, CTEs, aliased tables. 
    1067 
    1068    .. versionadded:: 2.0 
    1069 
    1070    """ 
    1071 
    1072    named_with_column = True 
    1073 
    1074    name: str 
    1075 
    1076    @util.preload_module("sqlalchemy.sql.sqltypes") 
    1077    def table_valued(self) -> TableValuedColumn[Any]: 
    1078        """Return a :class:`_sql.TableValuedColumn` object for this 
    1079        :class:`_expression.FromClause`. 
    1080 
    1081        A :class:`_sql.TableValuedColumn` is a :class:`_sql.ColumnElement` that 
    1082        represents a complete row in a table. Support for this construct is 
    1083        backend dependent, and is supported in various forms by backends 
    1084        such as PostgreSQL, Oracle Database and SQL Server. 
    1085 
    1086        E.g.: 
    1087 
    1088        .. sourcecode:: pycon+sql 
    1089 
    1090            >>> from sqlalchemy import select, column, func, table 
    1091            >>> a = table("a", column("id"), column("x"), column("y")) 
    1092            >>> stmt = select(func.row_to_json(a.table_valued())) 
    1093            >>> print(stmt) 
    1094            {printsql}SELECT row_to_json(a) AS row_to_json_1 
    1095            FROM a 
    1096 
    1097        .. versionadded:: 1.4.0b2 
    1098 
    1099        .. seealso:: 
    1100 
    1101            :ref:`tutorial_functions` - in the :ref:`unified_tutorial` 
    1102 
    1103        """ 
    1104        return TableValuedColumn(self, type_api.TABLEVALUE) 
    1105 
    1106 
    1107class SelectLabelStyle(Enum): 
    1108    """Label style constants that may be passed to 
    1109    :meth:`_sql.Select.set_label_style`.""" 
    1110 
    1111    LABEL_STYLE_NONE = 0 
    1112    """Label style indicating no automatic labeling should be applied to the 
    1113    columns clause of a SELECT statement. 
    1114 
    1115    Below, the columns named ``columna`` are both rendered as is, meaning that 
    1116    the name ``columna`` can only refer to the first occurrence of this name 
    1117    within a result set, as well as if the statement were used as a subquery: 
    1118 
    1119    .. sourcecode:: pycon+sql 
    1120 
    1121        >>> from sqlalchemy import table, column, select, true, LABEL_STYLE_NONE 
    1122        >>> table1 = table("table1", column("columna"), column("columnb")) 
    1123        >>> table2 = table("table2", column("columna"), column("columnc")) 
    1124        >>> print( 
    1125        ...     select(table1, table2) 
    1126        ...     .join(table2, true()) 
    1127        ...     .set_label_style(LABEL_STYLE_NONE) 
    1128        ... ) 
    1129        {printsql}SELECT table1.columna, table1.columnb, table2.columna, table2.columnc 
    1130        FROM table1 JOIN table2 ON true 
    1131 
    1132    Used with the :meth:`_sql.Select.set_label_style` method. 
    1133 
    1134    .. versionadded:: 1.4 
    1135 
    1136    """  # noqa: E501 
    1137 
    1138    LABEL_STYLE_TABLENAME_PLUS_COL = 1 
    1139    """Label style indicating all columns should be labeled as 
    1140    ``<tablename>_<columnname>`` when generating the columns clause of a SELECT 
    1141    statement, to disambiguate same-named columns referenced from different 
    1142    tables, aliases, or subqueries. 
    1143 
    1144    Below, all column names are given a label so that the two same-named 
    1145    columns ``columna`` are disambiguated as ``table1_columna`` and 
    1146    ``table2_columna``: 
    1147 
    1148    .. sourcecode:: pycon+sql 
    1149 
    1150        >>> from sqlalchemy import ( 
    1151        ...     table, 
    1152        ...     column, 
    1153        ...     select, 
    1154        ...     true, 
    1155        ...     LABEL_STYLE_TABLENAME_PLUS_COL, 
    1156        ... ) 
    1157        >>> table1 = table("table1", column("columna"), column("columnb")) 
    1158        >>> table2 = table("table2", column("columna"), column("columnc")) 
    1159        >>> print( 
    1160        ...     select(table1, table2) 
    1161        ...     .join(table2, true()) 
    1162        ...     .set_label_style(LABEL_STYLE_TABLENAME_PLUS_COL) 
    1163        ... ) 
    1164        {printsql}SELECT table1.columna AS table1_columna, table1.columnb AS table1_columnb, table2.columna AS table2_columna, table2.columnc AS table2_columnc 
    1165        FROM table1 JOIN table2 ON true 
    1166 
    1167    Used with the :meth:`_sql.GenerativeSelect.set_label_style` method. 
    1168    Equivalent to the legacy method ``Select.apply_labels()``; 
    1169    :data:`_sql.LABEL_STYLE_TABLENAME_PLUS_COL` is SQLAlchemy's legacy 
    1170    auto-labeling style. :data:`_sql.LABEL_STYLE_DISAMBIGUATE_ONLY` provides a 
    1171    less intrusive approach to disambiguation of same-named column expressions. 
    1172 
    1173 
    1174    .. versionadded:: 1.4 
    1175 
    1176    """  # noqa: E501 
    1177 
    1178    LABEL_STYLE_DISAMBIGUATE_ONLY = 2 
    1179    """Label style indicating that columns with a name that conflicts with 
    1180    an existing name should be labeled with a semi-anonymizing label 
    1181    when generating the columns clause of a SELECT statement. 
    1182 
    1183    Below, most column names are left unaffected, except for the second 
    1184    occurrence of the name ``columna``, which is labeled using the 
    1185    label ``columna_1`` to disambiguate it from that of ``tablea.columna``: 
    1186 
    1187    .. sourcecode:: pycon+sql 
    1188 
    1189        >>> from sqlalchemy import ( 
    1190        ...     table, 
    1191        ...     column, 
    1192        ...     select, 
    1193        ...     true, 
    1194        ...     LABEL_STYLE_DISAMBIGUATE_ONLY, 
    1195        ... ) 
    1196        >>> table1 = table("table1", column("columna"), column("columnb")) 
    1197        >>> table2 = table("table2", column("columna"), column("columnc")) 
    1198        >>> print( 
    1199        ...     select(table1, table2) 
    1200        ...     .join(table2, true()) 
    1201        ...     .set_label_style(LABEL_STYLE_DISAMBIGUATE_ONLY) 
    1202        ... ) 
    1203        {printsql}SELECT table1.columna, table1.columnb, table2.columna AS columna_1, table2.columnc 
    1204        FROM table1 JOIN table2 ON true 
    1205 
    1206    Used with the :meth:`_sql.GenerativeSelect.set_label_style` method, 
    1207    :data:`_sql.LABEL_STYLE_DISAMBIGUATE_ONLY` is the default labeling style 
    1208    for all SELECT statements outside of :term:`1.x style` ORM queries. 
    1209 
    1210    .. versionadded:: 1.4 
    1211 
    1212    """  # noqa: E501 
    1213 
    1214    LABEL_STYLE_DEFAULT = LABEL_STYLE_DISAMBIGUATE_ONLY 
    1215    """The default label style, refers to 
    1216    :data:`_sql.LABEL_STYLE_DISAMBIGUATE_ONLY`. 
    1217 
    1218    .. versionadded:: 1.4 
    1219 
    1220    """ 
    1221 
    1222    LABEL_STYLE_LEGACY_ORM = 3 
    1223 
    1224 
    1225( 
    1226    LABEL_STYLE_NONE, 
    1227    LABEL_STYLE_TABLENAME_PLUS_COL, 
    1228    LABEL_STYLE_DISAMBIGUATE_ONLY, 
    1229    _, 
    1230) = list(SelectLabelStyle) 
    1231 
    1232LABEL_STYLE_DEFAULT = LABEL_STYLE_DISAMBIGUATE_ONLY 
    1233 
    1234 
    1235class Join(roles.DMLTableRole, FromClause): 
    1236    """Represent a ``JOIN`` construct between two 
    1237    :class:`_expression.FromClause` 
    1238    elements. 
    1239 
    1240    The public constructor function for :class:`_expression.Join` 
    1241    is the module-level 
    1242    :func:`_expression.join()` function, as well as the 
    1243    :meth:`_expression.FromClause.join` method 
    1244    of any :class:`_expression.FromClause` (e.g. such as 
    1245    :class:`_schema.Table`). 
    1246 
    1247    .. seealso:: 
    1248 
    1249        :func:`_expression.join` 
    1250 
    1251        :meth:`_expression.FromClause.join` 
    1252 
    1253    """ 
    1254 
    1255    __visit_name__ = "join" 
    1256 
    1257    _traverse_internals: _TraverseInternalsType = [ 
    1258        ("left", InternalTraversal.dp_clauseelement), 
    1259        ("right", InternalTraversal.dp_clauseelement), 
    1260        ("onclause", InternalTraversal.dp_clauseelement), 
    1261        ("isouter", InternalTraversal.dp_boolean), 
    1262        ("full", InternalTraversal.dp_boolean), 
    1263    ] 
    1264 
    1265    _is_join = True 
    1266 
    1267    left: FromClause 
    1268    right: FromClause 
    1269    onclause: Optional[ColumnElement[bool]] 
    1270    isouter: bool 
    1271    full: bool 
    1272 
    1273    def __init__( 
    1274        self, 
    1275        left: _FromClauseArgument, 
    1276        right: _FromClauseArgument, 
    1277        onclause: Optional[_OnClauseArgument] = None, 
    1278        isouter: bool = False, 
    1279        full: bool = False, 
    1280    ): 
    1281        """Construct a new :class:`_expression.Join`. 
    1282 
    1283        The usual entrypoint here is the :func:`_expression.join` 
    1284        function or the :meth:`_expression.FromClause.join` method of any 
    1285        :class:`_expression.FromClause` object. 
    1286 
    1287        """ 
    1288 
    1289        # when deannotate was removed here, callcounts went up for ORM 
    1290        # compilation of eager joins, since there were more comparisons of 
    1291        # annotated objects.   test_orm.py -> test_fetch_results 
    1292        # was therefore changed to show a more real-world use case, where the 
    1293        # compilation is cached; there's no change in post-cache callcounts. 
    1294        # callcounts for a single compilation in that particular test 
    1295        # that includes about eight joins about 1100 extra fn calls, from 
    1296        # 29200 -> 30373 
    1297 
    1298        self.left = coercions.expect( 
    1299            roles.FromClauseRole, 
    1300            left, 
    1301        ) 
    1302        self.right = coercions.expect( 
    1303            roles.FromClauseRole, 
    1304            right, 
    1305        ).self_group() 
    1306 
    1307        if onclause is None: 
    1308            self.onclause = self._match_primaries(self.left, self.right) 
    1309        else: 
    1310            # note: taken from If91f61527236fd4d7ae3cad1f24c38be921c90ba 
    1311            # not merged yet 
    1312            self.onclause = coercions.expect( 
    1313                roles.OnClauseRole, onclause 
    1314            ).self_group(against=operators._asbool) 
    1315 
    1316        self.isouter = isouter 
    1317        self.full = full 
    1318 
    1319    @util.ro_non_memoized_property 
    1320    def description(self) -> str: 
    1321        return "Join object on %s(%d) and %s(%d)" % ( 
    1322            self.left.description, 
    1323            id(self.left), 
    1324            self.right.description, 
    1325            id(self.right), 
    1326        ) 
    1327 
    1328    def is_derived_from(self, fromclause: Optional[FromClause]) -> bool: 
    1329        return ( 
    1330            # use hash() to ensure direct comparison to annotated works 
    1331            # as well 
    1332            hash(fromclause) == hash(self) 
    1333            or self.left.is_derived_from(fromclause) 
    1334            or self.right.is_derived_from(fromclause) 
    1335        ) 
    1336 
    1337    def self_group( 
    1338        self, against: Optional[OperatorType] = None 
    1339    ) -> FromGrouping: 
    1340        return FromGrouping(self) 
    1341 
    1342    @util.preload_module("sqlalchemy.sql.util") 
    1343    def _populate_column_collection( 
    1344        self, 
    1345        columns: ColumnCollection[str, KeyedColumnElement[Any]], 
    1346        primary_key: ColumnSet, 
    1347        foreign_keys: Set[KeyedColumnElement[Any]], 
    1348    ) -> None: 
    1349        sqlutil = util.preloaded.sql_util 
    1350        _columns: List[KeyedColumnElement[Any]] = [c for c in self.left.c] + [ 
    1351            c for c in self.right.c 
    1352        ] 
    1353 
    1354        primary_key.extend( 
    1355            sqlutil.reduce_columns( 
    1356                (c for c in _columns if c.primary_key), self.onclause 
    1357            ) 
    1358        ) 
    1359        columns._populate_separate_keys( 
    1360            (col._tq_key_label, col) for col in _columns  # type: ignore 
    1361        ) 
    1362        foreign_keys.update( 
    1363            itertools.chain(*[col.foreign_keys for col in _columns])  # type: ignore  # noqa: E501 
    1364        ) 
    1365 
    1366    def _copy_internals( 
    1367        self, clone: _CloneCallableType = _clone, **kw: Any 
    1368    ) -> None: 
    1369        # see Select._copy_internals() for similar concept 
    1370 
    1371        # here we pre-clone "left" and "right" so that we can 
    1372        # determine the new FROM clauses 
    1373        all_the_froms = set( 
    1374            itertools.chain( 
    1375                _from_objects(self.left), 
    1376                _from_objects(self.right), 
    1377            ) 
    1378        ) 
    1379 
    1380        # run the clone on those.  these will be placed in the 
    1381        # cache used by the clone function 
    1382        new_froms = {f: clone(f, **kw) for f in all_the_froms} 
    1383 
    1384        # set up a special replace function that will replace for 
    1385        # ColumnClause with parent table referring to those 
    1386        # replaced FromClause objects 
    1387        def replace( 
    1388            obj: Union[BinaryExpression[Any], ColumnClause[Any]], 
    1389            **kw: Any, 
    1390        ) -> Optional[KeyedColumnElement[Any]]: 
    1391            if isinstance(obj, ColumnClause) and obj.table in new_froms: 
    1392                newelem = new_froms[obj.table].corresponding_column(obj) 
    1393                return newelem 
    1394            return None 
    1395 
    1396        kw["replace"] = replace 
    1397 
    1398        # run normal _copy_internals.  the clones for 
    1399        # left and right will come from the clone function's 
    1400        # cache 
    1401        super()._copy_internals(clone=clone, **kw) 
    1402 
    1403        self._reset_memoizations() 
    1404 
    1405    def _refresh_for_new_column(self, column: ColumnElement[Any]) -> None: 
    1406        super()._refresh_for_new_column(column) 
    1407        self.left._refresh_for_new_column(column) 
    1408        self.right._refresh_for_new_column(column) 
    1409 
    1410    def _match_primaries( 
    1411        self, 
    1412        left: FromClause, 
    1413        right: FromClause, 
    1414    ) -> ColumnElement[bool]: 
    1415        if isinstance(left, Join): 
    1416            left_right = left.right 
    1417        else: 
    1418            left_right = None 
    1419        return self._join_condition(left, right, a_subset=left_right) 
    1420 
    1421    @classmethod 
    1422    def _join_condition( 
    1423        cls, 
    1424        a: FromClause, 
    1425        b: FromClause, 
    1426        *, 
    1427        a_subset: Optional[FromClause] = None, 
    1428        consider_as_foreign_keys: Optional[ 
    1429            AbstractSet[ColumnClause[Any]] 
    1430        ] = None, 
    1431    ) -> ColumnElement[bool]: 
    1432        """Create a join condition between two tables or selectables. 
    1433 
    1434        See sqlalchemy.sql.util.join_condition() for full docs. 
    1435 
    1436        """ 
    1437        constraints = cls._joincond_scan_left_right( 
    1438            a, a_subset, b, consider_as_foreign_keys 
    1439        ) 
    1440 
    1441        if len(constraints) > 1: 
    1442            cls._joincond_trim_constraints( 
    1443                a, b, constraints, consider_as_foreign_keys 
    1444            ) 
    1445 
    1446        if len(constraints) == 0: 
    1447            if isinstance(b, FromGrouping): 
    1448                hint = ( 
    1449                    " Perhaps you meant to convert the right side to a " 
    1450                    "subquery using alias()?" 
    1451                ) 
    1452            else: 
    1453                hint = "" 
    1454            raise exc.NoForeignKeysError( 
    1455                "Can't find any foreign key relationships " 
    1456                "between '%s' and '%s'.%s" 
    1457                % (a.description, b.description, hint) 
    1458            ) 
    1459 
    1460        crit = [(x == y) for x, y in list(constraints.values())[0]] 
    1461        if len(crit) == 1: 
    1462            return crit[0] 
    1463        else: 
    1464            return and_(*crit) 
    1465 
    1466    @classmethod 
    1467    def _can_join( 
    1468        cls, 
    1469        left: FromClause, 
    1470        right: FromClause, 
    1471        *, 
    1472        consider_as_foreign_keys: Optional[ 
    1473            AbstractSet[ColumnClause[Any]] 
    1474        ] = None, 
    1475    ) -> bool: 
    1476        if isinstance(left, Join): 
    1477            left_right = left.right 
    1478        else: 
    1479            left_right = None 
    1480 
    1481        constraints = cls._joincond_scan_left_right( 
    1482            a=left, 
    1483            b=right, 
    1484            a_subset=left_right, 
    1485            consider_as_foreign_keys=consider_as_foreign_keys, 
    1486        ) 
    1487 
    1488        return bool(constraints) 
    1489 
    1490    @classmethod 
    1491    @util.preload_module("sqlalchemy.sql.util") 
    1492    def _joincond_scan_left_right( 
    1493        cls, 
    1494        a: FromClause, 
    1495        a_subset: Optional[FromClause], 
    1496        b: FromClause, 
    1497        consider_as_foreign_keys: Optional[AbstractSet[ColumnClause[Any]]], 
    1498    ) -> collections.defaultdict[ 
    1499        Optional[ForeignKeyConstraint], 
    1500        List[Tuple[ColumnClause[Any], ColumnClause[Any]]], 
    1501    ]: 
    1502        sql_util = util.preloaded.sql_util 
    1503 
    1504        a = coercions.expect(roles.FromClauseRole, a) 
    1505        b = coercions.expect(roles.FromClauseRole, b) 
    1506 
    1507        constraints: collections.defaultdict[ 
    1508            Optional[ForeignKeyConstraint], 
    1509            List[Tuple[ColumnClause[Any], ColumnClause[Any]]], 
    1510        ] = collections.defaultdict(list) 
    1511 
    1512        for left in (a_subset, a): 
    1513            if left is None: 
    1514                continue 
    1515            for fk in sorted( 
    1516                b.foreign_keys, 
    1517                key=lambda fk: fk.parent._creation_order, 
    1518            ): 
    1519                if ( 
    1520                    consider_as_foreign_keys is not None 
    1521                    and fk.parent not in consider_as_foreign_keys 
    1522                ): 
    1523                    continue 
    1524                try: 
    1525                    col = fk.get_referent(left) 
    1526                except exc.NoReferenceError as nrte: 
    1527                    table_names = {t.name for t in sql_util.find_tables(left)} 
    1528                    if nrte.table_name in table_names: 
    1529                        raise 
    1530                    else: 
    1531                        continue 
    1532 
    1533                if col is not None: 
    1534                    constraints[fk.constraint].append((col, fk.parent)) 
    1535            if left is not b: 
    1536                for fk in sorted( 
    1537                    left.foreign_keys, 
    1538                    key=lambda fk: fk.parent._creation_order, 
    1539                ): 
    1540                    if ( 
    1541                        consider_as_foreign_keys is not None 
    1542                        and fk.parent not in consider_as_foreign_keys 
    1543                    ): 
    1544                        continue 
    1545                    try: 
    1546                        col = fk.get_referent(b) 
    1547                    except exc.NoReferenceError as nrte: 
    1548                        table_names = {t.name for t in sql_util.find_tables(b)} 
    1549                        if nrte.table_name in table_names: 
    1550                            raise 
    1551                        else: 
    1552                            continue 
    1553 
    1554                    if col is not None: 
    1555                        constraints[fk.constraint].append((col, fk.parent)) 
    1556            if constraints: 
    1557                break 
    1558        return constraints 
    1559 
    1560    @classmethod 
    1561    def _joincond_trim_constraints( 
    1562        cls, 
    1563        a: FromClause, 
    1564        b: FromClause, 
    1565        constraints: Dict[Any, Any], 
    1566        consider_as_foreign_keys: Optional[Any], 
    1567    ) -> None: 
    1568        # more than one constraint matched.  narrow down the list 
    1569        # to include just those FKCs that match exactly to 
    1570        # "consider_as_foreign_keys". 
    1571        if consider_as_foreign_keys: 
    1572            for const in list(constraints): 
    1573                if {f.parent for f in const.elements} != set( 
    1574                    consider_as_foreign_keys 
    1575                ): 
    1576                    del constraints[const] 
    1577 
    1578        # if still multiple constraints, but 
    1579        # they all refer to the exact same end result, use it. 
    1580        if len(constraints) > 1: 
    1581            dedupe = {tuple(crit) for crit in constraints.values()} 
    1582            if len(dedupe) == 1: 
    1583                key = list(constraints)[0] 
    1584                constraints = {key: constraints[key]} 
    1585 
    1586        if len(constraints) != 1: 
    1587            raise exc.AmbiguousForeignKeysError( 
    1588                "Can't determine join between '%s' and '%s'; " 
    1589                "tables have more than one foreign key " 
    1590                "constraint relationship between them. " 
    1591                "Please specify the 'onclause' of this " 
    1592                "join explicitly." % (a.description, b.description) 
    1593            ) 
    1594 
    1595    def select(self) -> Select[Unpack[TupleAny]]: 
    1596        r"""Create a :class:`_expression.Select` from this 
    1597        :class:`_expression.Join`. 
    1598 
    1599        E.g.:: 
    1600 
    1601            stmt = table_a.join(table_b, table_a.c.id == table_b.c.a_id) 
    1602 
    1603            stmt = stmt.select() 
    1604 
    1605        The above will produce a SQL string resembling: 
    1606 
    1607        .. sourcecode:: sql 
    1608 
    1609            SELECT table_a.id, table_a.col, table_b.id, table_b.a_id 
    1610            FROM table_a JOIN table_b ON table_a.id = table_b.a_id 
    1611 
    1612        """ 
    1613        return Select(self.left, self.right).select_from(self) 
    1614 
    1615    @util.preload_module("sqlalchemy.sql.util") 
    1616    def _anonymous_fromclause( 
    1617        self, name: Optional[str] = None, flat: bool = False 
    1618    ) -> TODO_Any: 
    1619        sqlutil = util.preloaded.sql_util 
    1620        if flat: 
    1621            if isinstance(self.left, (FromGrouping, Join)): 
    1622                left_name = name  # will recurse 
    1623            else: 
    1624                if name and isinstance(self.left, NamedFromClause): 
    1625                    left_name = f"{name}_{self.left.name}" 
    1626                else: 
    1627                    left_name = name 
    1628            if isinstance(self.right, (FromGrouping, Join)): 
    1629                right_name = name  # will recurse 
    1630            else: 
    1631                if name and isinstance(self.right, NamedFromClause): 
    1632                    right_name = f"{name}_{self.right.name}" 
    1633                else: 
    1634                    right_name = name 
    1635            left_a, right_a = ( 
    1636                self.left._anonymous_fromclause(name=left_name, flat=flat), 
    1637                self.right._anonymous_fromclause(name=right_name, flat=flat), 
    1638            ) 
    1639            adapter = sqlutil.ClauseAdapter(left_a).chain( 
    1640                sqlutil.ClauseAdapter(right_a) 
    1641            ) 
    1642 
    1643            return left_a.join( 
    1644                right_a, 
    1645                adapter.traverse(self.onclause), 
    1646                isouter=self.isouter, 
    1647                full=self.full, 
    1648            ) 
    1649        else: 
    1650            return ( 
    1651                self.select() 
    1652                .set_label_style(LABEL_STYLE_TABLENAME_PLUS_COL) 
    1653                .correlate(None) 
    1654                .alias(name) 
    1655            ) 
    1656 
    1657    @util.ro_non_memoized_property 
    1658    def _hide_froms(self) -> Iterable[FromClause]: 
    1659        return itertools.chain( 
    1660            *[_from_objects(x.left, x.right) for x in self._cloned_set] 
    1661        ) 
    1662 
    1663    @util.ro_non_memoized_property 
    1664    def _from_objects(self) -> List[FromClause]: 
    1665        self_list: List[FromClause] = [self] 
    1666        return self_list + self.left._from_objects + self.right._from_objects 
    1667 
    1668 
    1669class NoInit: 
    1670    def __init__(self, *arg: Any, **kw: Any): 
    1671        raise NotImplementedError( 
    1672            "The %s class is not intended to be constructed " 
    1673            "directly.  Please use the %s() standalone " 
    1674            "function or the %s() method available from appropriate " 
    1675            "selectable objects." 
    1676            % ( 
    1677                self.__class__.__name__, 
    1678                self.__class__.__name__.lower(), 
    1679                self.__class__.__name__.lower(), 
    1680            ) 
    1681        ) 
    1682 
    1683 
    1684class LateralFromClause(NamedFromClause): 
    1685    """mark a FROM clause as being able to render directly as LATERAL""" 
    1686 
    1687 
    1688# FromClause -> 
    1689#   AliasedReturnsRows 
    1690#        -> Alias   only for FromClause 
    1691#        -> Subquery  only for SelectBase 
    1692#        -> CTE only for HasCTE -> SelectBase, DML 
    1693#        -> Lateral -> FromClause, but we accept SelectBase 
    1694#           w/ non-deprecated coercion 
    1695#        -> TableSample -> only for FromClause 
    1696 
    1697 
    1698class AliasedReturnsRows(NoInit, NamedFromClause): 
    1699    """Base class of aliases against tables, subqueries, and other 
    1700    selectables.""" 
    1701 
    1702    _is_from_container = True 
    1703 
    1704    _supports_derived_columns = False 
    1705 
    1706    element: ReturnsRows 
    1707 
    1708    _traverse_internals: _TraverseInternalsType = [ 
    1709        ("element", InternalTraversal.dp_clauseelement), 
    1710        ("name", InternalTraversal.dp_anon_name), 
    1711    ] 
    1712 
    1713    @classmethod 
    1714    def _construct( 
    1715        cls, 
    1716        selectable: Any, 
    1717        *, 
    1718        name: Optional[str] = None, 
    1719        **kw: Any, 
    1720    ) -> Self: 
    1721        obj = cls.__new__(cls) 
    1722        obj._init(selectable, name=name, **kw) 
    1723        return obj 
    1724 
    1725    def _init(self, selectable: Any, *, name: Optional[str] = None) -> None: 
    1726        self.element = coercions.expect( 
    1727            roles.ReturnsRowsRole, selectable, apply_propagate_attrs=self 
    1728        ) 
    1729        self.element = selectable 
    1730        self._orig_name = name 
    1731        if name is None: 
    1732            if ( 
    1733                isinstance(selectable, FromClause) 
    1734                and selectable.named_with_column 
    1735            ): 
    1736                name = getattr(selectable, "name", None) 
    1737                if isinstance(name, _anonymous_label): 
    1738                    name = None 
    1739            name = _anonymous_label.safe_construct(id(self), name or "anon") 
    1740        self.name = name 
    1741 
    1742    def _refresh_for_new_column(self, column: ColumnElement[Any]) -> None: 
    1743        super()._refresh_for_new_column(column) 
    1744        self.element._refresh_for_new_column(column) 
    1745 
    1746    def _populate_column_collection( 
    1747        self, 
    1748        columns: ColumnCollection[str, KeyedColumnElement[Any]], 
    1749        primary_key: ColumnSet, 
    1750        foreign_keys: Set[KeyedColumnElement[Any]], 
    1751    ) -> None: 
    1752        self.element._generate_fromclause_column_proxies( 
    1753            self, columns, primary_key=primary_key, foreign_keys=foreign_keys 
    1754        ) 
    1755 
    1756    @util.ro_non_memoized_property 
    1757    def description(self) -> str: 
    1758        name = self.name 
    1759        if isinstance(name, _anonymous_label): 
    1760            return "anon_1" 
    1761 
    1762        return name 
    1763 
    1764    @util.ro_non_memoized_property 
    1765    def implicit_returning(self) -> bool: 
    1766        return self.element.implicit_returning  # type: ignore 
    1767 
    1768    @property 
    1769    def original(self) -> ReturnsRows: 
    1770        """Legacy for dialects that are referring to Alias.original.""" 
    1771        return self.element 
    1772 
    1773    def is_derived_from(self, fromclause: Optional[FromClause]) -> bool: 
    1774        if fromclause in self._cloned_set: 
    1775            return True 
    1776        return self.element.is_derived_from(fromclause) 
    1777 
    1778    def _copy_internals( 
    1779        self, clone: _CloneCallableType = _clone, **kw: Any 
    1780    ) -> None: 
    1781        existing_element = self.element 
    1782 
    1783        super()._copy_internals(clone=clone, **kw) 
    1784 
    1785        # the element clone is usually against a Table that returns the 
    1786        # same object.  don't reset exported .c. collections and other 
    1787        # memoized details if it was not changed.  this saves a lot on 
    1788        # performance. 
    1789        if existing_element is not self.element: 
    1790            self._reset_column_collection() 
    1791 
    1792    @property 
    1793    def _from_objects(self) -> List[FromClause]: 
    1794        return [self] 
    1795 
    1796 
    1797class FromClauseAlias(AliasedReturnsRows): 
    1798    element: FromClause 
    1799 
    1800    @util.ro_non_memoized_property 
    1801    def description(self) -> str: 
    1802        name = self.name 
    1803        if isinstance(name, _anonymous_label): 
    1804            return f"Anonymous alias of {self.element.description}" 
    1805 
    1806        return name 
    1807 
    1808 
    1809class Alias(roles.DMLTableRole, FromClauseAlias): 
    1810    """Represents an table or selectable alias (AS). 
    1811 
    1812    Represents an alias, as typically applied to any table or 
    1813    sub-select within a SQL statement using the ``AS`` keyword (or 
    1814    without the keyword on certain databases such as Oracle Database). 
    1815 
    1816    This object is constructed from the :func:`_expression.alias` module 
    1817    level function as well as the :meth:`_expression.FromClause.alias` 
    1818    method available 
    1819    on all :class:`_expression.FromClause` subclasses. 
    1820 
    1821    .. seealso:: 
    1822 
    1823        :meth:`_expression.FromClause.alias` 
    1824 
    1825    """ 
    1826 
    1827    __visit_name__ = "alias" 
    1828 
    1829    inherit_cache = True 
    1830 
    1831    element: FromClause 
    1832 
    1833    @classmethod 
    1834    def _factory( 
    1835        cls, 
    1836        selectable: FromClause, 
    1837        name: Optional[str] = None, 
    1838        flat: bool = False, 
    1839    ) -> NamedFromClause: 
    1840        return coercions.expect(roles.FromClauseRole, selectable).alias( 
    1841            name=name, flat=flat 
    1842        ) 
    1843 
    1844 
    1845class TableValuedAlias(LateralFromClause, Alias): 
    1846    """An alias against a "table valued" SQL function. 
    1847 
    1848    This construct provides for a SQL function that returns columns 
    1849    to be used in the FROM clause of a SELECT statement.   The 
    1850    object is generated using the :meth:`_functions.FunctionElement.table_valued` 
    1851    method, e.g.: 
    1852 
    1853    .. sourcecode:: pycon+sql 
    1854 
    1855        >>> from sqlalchemy import select, func 
    1856        >>> fn = func.json_array_elements_text('["one", "two", "three"]').table_valued( 
    1857        ...     "value" 
    1858        ... ) 
    1859        >>> print(select(fn.c.value)) 
    1860        {printsql}SELECT anon_1.value 
    1861        FROM json_array_elements_text(:json_array_elements_text_1) AS anon_1 
    1862 
    1863    .. versionadded:: 1.4.0b2 
    1864 
    1865    .. seealso:: 
    1866 
    1867        :ref:`tutorial_functions_table_valued` - in the :ref:`unified_tutorial` 
    1868 
    1869    """  # noqa: E501 
    1870 
    1871    __visit_name__ = "table_valued_alias" 
    1872 
    1873    _supports_derived_columns = True 
    1874    _render_derived = False 
    1875    _render_derived_w_types = False 
    1876    joins_implicitly = False 
    1877 
    1878    _traverse_internals: _TraverseInternalsType = [ 
    1879        ("element", InternalTraversal.dp_clauseelement), 
    1880        ("name", InternalTraversal.dp_anon_name), 
    1881        ("_tableval_type", InternalTraversal.dp_type), 
    1882        ("_render_derived", InternalTraversal.dp_boolean), 
    1883        ("_render_derived_w_types", InternalTraversal.dp_boolean), 
    1884    ] 
    1885 
    1886    def _init( 
    1887        self, 
    1888        selectable: Any, 
    1889        *, 
    1890        name: Optional[str] = None, 
    1891        table_value_type: Optional[TableValueType] = None, 
    1892        joins_implicitly: bool = False, 
    1893    ) -> None: 
    1894        super()._init(selectable, name=name) 
    1895 
    1896        self.joins_implicitly = joins_implicitly 
    1897        self._tableval_type = ( 
    1898            type_api.TABLEVALUE 
    1899            if table_value_type is None 
    1900            else table_value_type 
    1901        ) 
    1902 
    1903    @HasMemoized.memoized_attribute 
    1904    def column(self) -> TableValuedColumn[Any]: 
    1905        """Return a column expression representing this 
    1906        :class:`_sql.TableValuedAlias`. 
    1907 
    1908        This accessor is used to implement the 
    1909        :meth:`_functions.FunctionElement.column_valued` method. See that 
    1910        method for further details. 
    1911 
    1912        E.g.: 
    1913 
    1914        .. sourcecode:: pycon+sql 
    1915 
    1916            >>> print(select(func.some_func().table_valued("value").column)) 
    1917            {printsql}SELECT anon_1 FROM some_func() AS anon_1 
    1918 
    1919        .. seealso:: 
    1920 
    1921            :meth:`_functions.FunctionElement.column_valued` 
    1922 
    1923        """ 
    1924 
    1925        return TableValuedColumn(self, self._tableval_type) 
    1926 
    1927    def alias( 
    1928        self, name: Optional[str] = None, flat: bool = False 
    1929    ) -> TableValuedAlias: 
    1930        """Return a new alias of this :class:`_sql.TableValuedAlias`. 
    1931 
    1932        This creates a distinct FROM object that will be distinguished 
    1933        from the original one when used in a SQL statement. 
    1934 
    1935        """ 
    1936 
    1937        tva: TableValuedAlias = TableValuedAlias._construct( 
    1938            self, 
    1939            name=name, 
    1940            table_value_type=self._tableval_type, 
    1941            joins_implicitly=self.joins_implicitly, 
    1942        ) 
    1943 
    1944        if self._render_derived: 
    1945            tva._render_derived = True 
    1946            tva._render_derived_w_types = self._render_derived_w_types 
    1947 
    1948        return tva 
    1949 
    1950    def lateral(self, name: Optional[str] = None) -> LateralFromClause: 
    1951        """Return a new :class:`_sql.TableValuedAlias` with the lateral flag 
    1952        set, so that it renders as LATERAL. 
    1953 
    1954        .. seealso:: 
    1955 
    1956            :func:`_expression.lateral` 
    1957 
    1958        """ 
    1959        tva = self.alias(name=name) 
    1960        tva._is_lateral = True 
    1961        return tva 
    1962 
    1963    def render_derived( 
    1964        self, 
    1965        name: Optional[str] = None, 
    1966        with_types: bool = False, 
    1967    ) -> TableValuedAlias: 
    1968        """Apply "render derived" to this :class:`_sql.TableValuedAlias`. 
    1969 
    1970        This has the effect of the individual column names listed out 
    1971        after the alias name in the "AS" sequence, e.g.: 
    1972 
    1973        .. sourcecode:: pycon+sql 
    1974 
    1975            >>> print( 
    1976            ...     select( 
    1977            ...         func.unnest(array(["one", "two", "three"])) 
    1978            ...         .table_valued("x", with_ordinality="o") 
    1979            ...         .render_derived() 
    1980            ...     ) 
    1981            ... ) 
    1982            {printsql}SELECT anon_1.x, anon_1.o 
    1983            FROM unnest(ARRAY[%(param_1)s, %(param_2)s, %(param_3)s]) WITH ORDINALITY AS anon_1(x, o) 
    1984 
    1985        The ``with_types`` keyword will render column types inline within 
    1986        the alias expression (this syntax currently applies to the 
    1987        PostgreSQL database): 
    1988 
    1989        .. sourcecode:: pycon+sql 
    1990 
    1991            >>> print( 
    1992            ...     select( 
    1993            ...         func.json_to_recordset('[{"a":1,"b":"foo"},{"a":"2","c":"bar"}]') 
    1994            ...         .table_valued(column("a", Integer), column("b", String)) 
    1995            ...         .render_derived(with_types=True) 
    1996            ...     ) 
    1997            ... ) 
    1998            {printsql}SELECT anon_1.a, anon_1.b FROM json_to_recordset(:json_to_recordset_1) 
    1999            AS anon_1(a INTEGER, b VARCHAR) 
    2000 
    2001        :param name: optional string name that will be applied to the alias 
    2002         generated.  If left as None, a unique anonymizing name will be used. 
    2003 
    2004        :param with_types: if True, the derived columns will include the 
    2005         datatype specification with each column. This is a special syntax 
    2006         currently known to be required by PostgreSQL for some SQL functions. 
    2007 
    2008        """  # noqa: E501 
    2009 
    2010        # note: don't use the @_generative system here, keep a reference 
    2011        # to the original object.  otherwise you can have re-use of the 
    2012        # python id() of the original which can cause name conflicts if 
    2013        # a new anon-name grabs the same identifier as the local anon-name 
    2014        # (just saw it happen on CI) 
    2015 
    2016        # construct against original to prevent memory growth 
    2017        # for repeated generations 
    2018        new_alias: TableValuedAlias = TableValuedAlias._construct( 
    2019            self.element, 
    2020            name=name, 
    2021            table_value_type=self._tableval_type, 
    2022            joins_implicitly=self.joins_implicitly, 
    2023        ) 
    2024        new_alias._render_derived = True 
    2025        new_alias._render_derived_w_types = with_types 
    2026        return new_alias 
    2027 
    2028 
    2029class Lateral(FromClauseAlias, LateralFromClause): 
    2030    """Represent a LATERAL subquery. 
    2031 
    2032    This object is constructed from the :func:`_expression.lateral` module 
    2033    level function as well as the :meth:`_expression.FromClause.lateral` 
    2034    method available 
    2035    on all :class:`_expression.FromClause` subclasses. 
    2036 
    2037    While LATERAL is part of the SQL standard, currently only more recent 
    2038    PostgreSQL versions provide support for this keyword. 
    2039 
    2040    .. seealso:: 
    2041 
    2042        :ref:`tutorial_lateral_correlation` -  overview of usage. 
    2043 
    2044    """ 
    2045 
    2046    __visit_name__ = "lateral" 
    2047    _is_lateral = True 
    2048 
    2049    inherit_cache = True 
    2050 
    2051    @classmethod 
    2052    def _factory( 
    2053        cls, 
    2054        selectable: Union[SelectBase, _FromClauseArgument], 
    2055        name: Optional[str] = None, 
    2056    ) -> LateralFromClause: 
    2057        return coercions.expect( 
    2058            roles.FromClauseRole, selectable, explicit_subquery=True 
    2059        ).lateral(name=name) 
    2060 
    2061 
    2062class TableSample(FromClauseAlias): 
    2063    """Represent a TABLESAMPLE clause. 
    2064 
    2065    This object is constructed from the :func:`_expression.tablesample` module 
    2066    level function as well as the :meth:`_expression.FromClause.tablesample` 
    2067    method 
    2068    available on all :class:`_expression.FromClause` subclasses. 
    2069 
    2070    .. seealso:: 
    2071 
    2072        :func:`_expression.tablesample` 
    2073 
    2074    """ 
    2075 
    2076    __visit_name__ = "tablesample" 
    2077 
    2078    _traverse_internals: _TraverseInternalsType = ( 
    2079        AliasedReturnsRows._traverse_internals 
    2080        + [ 
    2081            ("sampling", InternalTraversal.dp_clauseelement), 
    2082            ("seed", InternalTraversal.dp_clauseelement), 
    2083        ] 
    2084    ) 
    2085 
    2086    @classmethod 
    2087    def _factory( 
    2088        cls, 
    2089        selectable: _FromClauseArgument, 
    2090        sampling: Union[float, Function[Any]], 
    2091        name: Optional[str] = None, 
    2092        seed: Optional[roles.ExpressionElementRole[Any]] = None, 
    2093    ) -> TableSample: 
    2094        return coercions.expect(roles.FromClauseRole, selectable).tablesample( 
    2095            sampling, name=name, seed=seed 
    2096        ) 
    2097 
    2098    @util.preload_module("sqlalchemy.sql.functions") 
    2099    def _init(  # type: ignore[override] 
    2100        self, 
    2101        selectable: Any, 
    2102        *, 
    2103        name: Optional[str] = None, 
    2104        sampling: Union[float, Function[Any]], 
    2105        seed: Optional[roles.ExpressionElementRole[Any]] = None, 
    2106    ) -> None: 
    2107        assert sampling is not None 
    2108        functions = util.preloaded.sql_functions 
    2109        if not isinstance(sampling, functions.Function): 
    2110            sampling = functions.func.system(sampling) 
    2111 
    2112        self.sampling: Function[Any] = sampling 
    2113        self.seed = seed 
    2114        super()._init(selectable, name=name) 
    2115 
    2116    def _get_method(self) -> Function[Any]: 
    2117        return self.sampling 
    2118 
    2119 
    2120class CTE( 
    2121    roles.DMLTableRole, 
    2122    roles.IsCTERole, 
    2123    Generative, 
    2124    HasPrefixes, 
    2125    HasSuffixes, 
    2126    AliasedReturnsRows, 
    2127): 
    2128    """Represent a Common Table Expression. 
    2129 
    2130    The :class:`_expression.CTE` object is obtained using the 
    2131    :meth:`_sql.SelectBase.cte` method from any SELECT statement. A less often 
    2132    available syntax also allows use of the :meth:`_sql.HasCTE.cte` method 
    2133    present on :term:`DML` constructs such as :class:`_sql.Insert`, 
    2134    :class:`_sql.Update` and 
    2135    :class:`_sql.Delete`.   See the :meth:`_sql.HasCTE.cte` method for 
    2136    usage details on CTEs. 
    2137 
    2138    .. seealso:: 
    2139 
    2140        :ref:`tutorial_subqueries_ctes` - in the 2.0 tutorial 
    2141 
    2142        :meth:`_sql.HasCTE.cte` - examples of calling styles 
    2143 
    2144    """ 
    2145 
    2146    __visit_name__ = "cte" 
    2147 
    2148    _traverse_internals: _TraverseInternalsType = ( 
    2149        AliasedReturnsRows._traverse_internals 
    2150        + [ 
    2151            ("_cte_alias", InternalTraversal.dp_clauseelement), 
    2152            ("_restates", InternalTraversal.dp_clauseelement), 
    2153            ("recursive", InternalTraversal.dp_boolean), 
    2154            ("nesting", InternalTraversal.dp_boolean), 
    2155        ] 
    2156        + HasPrefixes._has_prefixes_traverse_internals 
    2157        + HasSuffixes._has_suffixes_traverse_internals 
    2158    ) 
    2159 
    2160    element: HasCTE 
    2161 
    2162    @classmethod 
    2163    def _factory( 
    2164        cls, 
    2165        selectable: HasCTE, 
    2166        name: Optional[str] = None, 
    2167        recursive: bool = False, 
    2168    ) -> CTE: 
    2169        r"""Return a new :class:`_expression.CTE`, 
    2170        or Common Table Expression instance. 
    2171 
    2172        Please see :meth:`_expression.HasCTE.cte` for detail on CTE usage. 
    2173 
    2174        """ 
    2175        return coercions.expect(roles.HasCTERole, selectable).cte( 
    2176            name=name, recursive=recursive 
    2177        ) 
    2178 
    2179    def _init( 
    2180        self, 
    2181        selectable: HasCTE, 
    2182        *, 
    2183        name: Optional[str] = None, 
    2184        recursive: bool = False, 
    2185        nesting: bool = False, 
    2186        _cte_alias: Optional[CTE] = None, 
    2187        _restates: Optional[CTE] = None, 
    2188        _prefixes: Optional[Tuple[()]] = None, 
    2189        _suffixes: Optional[Tuple[()]] = None, 
    2190    ) -> None: 
    2191        self.recursive = recursive 
    2192        self.nesting = nesting 
    2193        self._cte_alias = _cte_alias 
    2194        # Keep recursivity reference with union/union_all 
    2195        self._restates = _restates 
    2196        if _prefixes: 
    2197            self._prefixes = _prefixes 
    2198        if _suffixes: 
    2199            self._suffixes = _suffixes 
    2200        super()._init(selectable, name=name) 
    2201 
    2202    def _populate_column_collection( 
    2203        self, 
    2204        columns: ColumnCollection[str, KeyedColumnElement[Any]], 
    2205        primary_key: ColumnSet, 
    2206        foreign_keys: Set[KeyedColumnElement[Any]], 
    2207    ) -> None: 
    2208        if self._cte_alias is not None: 
    2209            self._cte_alias._generate_fromclause_column_proxies( 
    2210                self, 
    2211                columns, 
    2212                primary_key=primary_key, 
    2213                foreign_keys=foreign_keys, 
    2214            ) 
    2215        else: 
    2216            self.element._generate_fromclause_column_proxies( 
    2217                self, 
    2218                columns, 
    2219                primary_key=primary_key, 
    2220                foreign_keys=foreign_keys, 
    2221            ) 
    2222 
    2223    def alias(self, name: Optional[str] = None, flat: bool = False) -> CTE: 
    2224        """Return an :class:`_expression.Alias` of this 
    2225        :class:`_expression.CTE`. 
    2226 
    2227        This method is a CTE-specific specialization of the 
    2228        :meth:`_expression.FromClause.alias` method. 
    2229 
    2230        .. seealso:: 
    2231 
    2232            :ref:`tutorial_using_aliases` 
    2233 
    2234            :func:`_expression.alias` 
    2235 
    2236        """ 
    2237        return CTE._construct( 
    2238            self.element, 
    2239            name=name, 
    2240            recursive=self.recursive, 
    2241            nesting=self.nesting, 
    2242            _cte_alias=self, 
    2243            _prefixes=self._prefixes, 
    2244            _suffixes=self._suffixes, 
    2245        ) 
    2246 
    2247    def union(self, *other: _SelectStatementForCompoundArgument[Any]) -> CTE: 
    2248        r"""Return a new :class:`_expression.CTE` with a SQL ``UNION`` 
    2249        of the original CTE against the given selectables provided 
    2250        as positional arguments. 
    2251 
    2252        :param \*other: one or more elements with which to create a 
    2253         UNION. 
    2254 
    2255         .. versionchanged:: 1.4.28 multiple elements are now accepted. 
    2256 
    2257        .. seealso:: 
    2258 
    2259            :meth:`_sql.HasCTE.cte` - examples of calling styles 
    2260 
    2261        """ 
    2262        assert is_select_statement( 
    2263            self.element 
    2264        ), f"CTE element f{self.element} does not support union()" 
    2265 
    2266        return CTE._construct( 
    2267            self.element.union(*other), 
    2268            name=self.name, 
    2269            recursive=self.recursive, 
    2270            nesting=self.nesting, 
    2271            _restates=self, 
    2272            _prefixes=self._prefixes, 
    2273            _suffixes=self._suffixes, 
    2274        ) 
    2275 
    2276    def union_all( 
    2277        self, *other: _SelectStatementForCompoundArgument[Any] 
    2278    ) -> CTE: 
    2279        r"""Return a new :class:`_expression.CTE` with a SQL ``UNION ALL`` 
    2280        of the original CTE against the given selectables provided 
    2281        as positional arguments. 
    2282 
    2283        :param \*other: one or more elements with which to create a 
    2284         UNION. 
    2285 
    2286         .. versionchanged:: 1.4.28 multiple elements are now accepted. 
    2287 
    2288        .. seealso:: 
    2289 
    2290            :meth:`_sql.HasCTE.cte` - examples of calling styles 
    2291 
    2292        """ 
    2293 
    2294        assert is_select_statement( 
    2295            self.element 
    2296        ), f"CTE element f{self.element} does not support union_all()" 
    2297 
    2298        return CTE._construct( 
    2299            self.element.union_all(*other), 
    2300            name=self.name, 
    2301            recursive=self.recursive, 
    2302            nesting=self.nesting, 
    2303            _restates=self, 
    2304            _prefixes=self._prefixes, 
    2305            _suffixes=self._suffixes, 
    2306        ) 
    2307 
    2308    def _get_reference_cte(self) -> CTE: 
    2309        """ 
    2310        A recursive CTE is updated to attach the recursive part. 
    2311        Updated CTEs should still refer to the original CTE. 
    2312        This function returns this reference identifier. 
    2313        """ 
    2314        return self._restates if self._restates is not None else self 
    2315 
    2316 
    2317class _CTEOpts(NamedTuple): 
    2318    nesting: bool 
    2319 
    2320 
    2321class _ColumnsPlusNames(NamedTuple): 
    2322    required_label_name: Optional[str] 
    2323    """ 
    2324    string label name, if non-None, must be rendered as a 
    2325    label, i.e. "AS <name>" 
    2326    """ 
    2327 
    2328    proxy_key: Optional[str] 
    2329    """ 
    2330    proxy_key that is to be part of the result map for this 
    2331    col.  this is also the key in a fromclause.c or 
    2332    select.selected_columns collection 
    2333    """ 
    2334 
    2335    fallback_label_name: Optional[str] 
    2336    """ 
    2337    name that can be used to render an "AS <name>" when 
    2338    we have to render a label even though 
    2339    required_label_name was not given 
    2340    """ 
    2341 
    2342    column: Union[ColumnElement[Any], TextClause] 
    2343    """ 
    2344    the ColumnElement itself 
    2345    """ 
    2346 
    2347    repeated: bool 
    2348    """ 
    2349    True if this is a duplicate of a previous column 
    2350    in the list of columns 
    2351    """ 
    2352 
    2353 
    2354class SelectsRows(ReturnsRows): 
    2355    """Sub-base of ReturnsRows for elements that deliver rows 
    2356    directly, namely SELECT and INSERT/UPDATE/DELETE..RETURNING""" 
    2357 
    2358    _label_style: SelectLabelStyle = LABEL_STYLE_NONE 
    2359 
    2360    def _generate_columns_plus_names( 
    2361        self, 
    2362        anon_for_dupe_key: bool, 
    2363        cols: Optional[_SelectIterable] = None, 
    2364    ) -> List[_ColumnsPlusNames]: 
    2365        """Generate column names as rendered in a SELECT statement by 
    2366        the compiler, as well as tokens used to populate the .c. collection 
    2367        on a :class:`.FromClause`. 
    2368 
    2369        This is distinct from the _column_naming_convention generator that's 
    2370        intended for population of the Select.selected_columns collection, 
    2371        different rules.   the collection returned here calls upon the 
    2372        _column_naming_convention as well. 
    2373 
    2374        """ 
    2375 
    2376        if cols is None: 
    2377            cols = self._all_selected_columns 
    2378 
    2379        key_naming_convention = SelectState._column_naming_convention( 
    2380            self._label_style 
    2381        ) 
    2382 
    2383        names = {} 
    2384 
    2385        result: List[_ColumnsPlusNames] = [] 
    2386        result_append = result.append 
    2387 
    2388        table_qualified = self._label_style is LABEL_STYLE_TABLENAME_PLUS_COL 
    2389        label_style_none = self._label_style is LABEL_STYLE_NONE 
    2390 
    2391        # a counter used for "dedupe" labels, which have double underscores 
    2392        # in them and are never referred by name; they only act 
    2393        # as positional placeholders.  they need only be unique within 
    2394        # the single columns clause they're rendered within (required by 
    2395        # some dbs such as mysql).  So their anon identity is tracked against 
    2396        # a fixed counter rather than hash() identity. 
    2397        dedupe_hash = 1 
    2398 
    2399        for c in cols: 
    2400            repeated = False 
    2401 
    2402            if not c._render_label_in_columns_clause: 
    2403                effective_name = required_label_name = fallback_label_name = ( 
    2404                    None 
    2405                ) 
    2406            elif label_style_none: 
    2407                if TYPE_CHECKING: 
    2408                    assert is_column_element(c) 
    2409 
    2410                effective_name = required_label_name = None 
    2411                fallback_label_name = c._non_anon_label or c._anon_name_label 
    2412            else: 
    2413                if TYPE_CHECKING: 
    2414                    assert is_column_element(c) 
    2415 
    2416                if table_qualified: 
    2417                    required_label_name = effective_name = ( 
    2418                        fallback_label_name 
    2419                    ) = c._tq_label 
    2420                else: 
    2421                    effective_name = fallback_label_name = c._non_anon_label 
    2422                    required_label_name = None 
    2423 
    2424                if effective_name is None: 
    2425                    # it seems like this could be _proxy_key and we would 
    2426                    # not need _expression_label but it isn't 
    2427                    # giving us a clue when to use anon_label instead 
    2428                    expr_label = c._expression_label 
    2429                    if expr_label is None: 
    2430                        repeated = c._anon_name_label in names 
    2431                        names[c._anon_name_label] = c 
    2432                        effective_name = required_label_name = None 
    2433 
    2434                        if repeated: 
    2435                            # here, "required_label_name" is sent as 
    2436                            # "None" and "fallback_label_name" is sent. 
    2437                            if table_qualified: 
    2438                                fallback_label_name = ( 
    2439                                    c._dedupe_anon_tq_label_idx(dedupe_hash) 
    2440                                ) 
    2441                                dedupe_hash += 1 
    2442                            else: 
    2443                                fallback_label_name = c._dedupe_anon_label_idx( 
    2444                                    dedupe_hash 
    2445                                ) 
    2446                                dedupe_hash += 1 
    2447                        else: 
    2448                            fallback_label_name = c._anon_name_label 
    2449                    else: 
    2450                        required_label_name = effective_name = ( 
    2451                            fallback_label_name 
    2452                        ) = expr_label 
    2453 
    2454            if effective_name is not None: 
    2455                if TYPE_CHECKING: 
    2456                    assert is_column_element(c) 
    2457 
    2458                if effective_name in names: 
    2459                    # when looking to see if names[name] is the same column as 
    2460                    # c, use hash(), so that an annotated version of the column 
    2461                    # is seen as the same as the non-annotated 
    2462                    if hash(names[effective_name]) != hash(c): 
    2463                        # different column under the same name.  apply 
    2464                        # disambiguating label 
    2465                        if table_qualified: 
    2466                            required_label_name = fallback_label_name = ( 
    2467                                c._anon_tq_label 
    2468                            ) 
    2469                        else: 
    2470                            required_label_name = fallback_label_name = ( 
    2471                                c._anon_name_label 
    2472                            ) 
    2473 
    2474                        if anon_for_dupe_key and required_label_name in names: 
    2475                            # here, c._anon_tq_label is definitely unique to 
    2476                            # that column identity (or annotated version), so 
    2477                            # this should always be true. 
    2478                            # this is also an infrequent codepath because 
    2479                            # you need two levels of duplication to be here 
    2480                            assert hash(names[required_label_name]) == hash(c) 
    2481 
    2482                            # the column under the disambiguating label is 
    2483                            # already present.  apply the "dedupe" label to 
    2484                            # subsequent occurrences of the column so that the 
    2485                            # original stays non-ambiguous 
    2486                            if table_qualified: 
    2487                                required_label_name = fallback_label_name = ( 
    2488                                    c._dedupe_anon_tq_label_idx(dedupe_hash) 
    2489                                ) 
    2490                                dedupe_hash += 1 
    2491                            else: 
    2492                                required_label_name = fallback_label_name = ( 
    2493                                    c._dedupe_anon_label_idx(dedupe_hash) 
    2494                                ) 
    2495                                dedupe_hash += 1 
    2496                            repeated = True 
    2497                        else: 
    2498                            names[required_label_name] = c 
    2499                    elif anon_for_dupe_key: 
    2500                        # same column under the same name. apply the "dedupe" 
    2501                        # label so that the original stays non-ambiguous 
    2502                        if table_qualified: 
    2503                            required_label_name = fallback_label_name = ( 
    2504                                c._dedupe_anon_tq_label_idx(dedupe_hash) 
    2505                            ) 
    2506                            dedupe_hash += 1 
    2507                        else: 
    2508                            required_label_name = fallback_label_name = ( 
    2509                                c._dedupe_anon_label_idx(dedupe_hash) 
    2510                            ) 
    2511                            dedupe_hash += 1 
    2512                        repeated = True 
    2513                else: 
    2514                    names[effective_name] = c 
    2515 
    2516            result_append( 
    2517                _ColumnsPlusNames( 
    2518                    required_label_name, 
    2519                    key_naming_convention(c), 
    2520                    fallback_label_name, 
    2521                    c, 
    2522                    repeated, 
    2523                ) 
    2524            ) 
    2525 
    2526        return result 
    2527 
    2528 
    2529class HasCTE(roles.HasCTERole, SelectsRows): 
    2530    """Mixin that declares a class to include CTE support.""" 
    2531 
    2532    _has_ctes_traverse_internals: _TraverseInternalsType = [ 
    2533        ("_independent_ctes", InternalTraversal.dp_clauseelement_list), 
    2534        ("_independent_ctes_opts", InternalTraversal.dp_plain_obj), 
    2535    ] 
    2536 
    2537    _independent_ctes: Tuple[CTE, ...] = () 
    2538    _independent_ctes_opts: Tuple[_CTEOpts, ...] = () 
    2539 
    2540    name_cte_columns: bool = False 
    2541    """indicates if this HasCTE as contained within a CTE should compel the CTE 
    2542    to render the column names of this object in the WITH clause. 
    2543 
    2544    .. versionadded:: 2.0.42 
    2545 
    2546    """ 
    2547 
    2548    @_generative 
    2549    def add_cte(self, *ctes: CTE, nest_here: bool = False) -> Self: 
    2550        r"""Add one or more :class:`_sql.CTE` constructs to this statement. 
    2551 
    2552        This method will associate the given :class:`_sql.CTE` constructs with 
    2553        the parent statement such that they will each be unconditionally 
    2554        rendered in the WITH clause of the final statement, even if not 
    2555        referenced elsewhere within the statement or any sub-selects. 
    2556 
    2557        The optional :paramref:`.HasCTE.add_cte.nest_here` parameter when set 
    2558        to True will have the effect that each given :class:`_sql.CTE` will 
    2559        render in a WITH clause rendered directly along with this statement, 
    2560        rather than being moved to the top of the ultimate rendered statement, 
    2561        even if this statement is rendered as a subquery within a larger 
    2562        statement. 
    2563 
    2564        This method has two general uses. One is to embed CTE statements that 
    2565        serve some purpose without being referenced explicitly, such as the use 
    2566        case of embedding a DML statement such as an INSERT or UPDATE as a CTE 
    2567        inline with a primary statement that may draw from its results 
    2568        indirectly.  The other is to provide control over the exact placement 
    2569        of a particular series of CTE constructs that should remain rendered 
    2570        directly in terms of a particular statement that may be nested in a 
    2571        larger statement. 
    2572 
    2573        E.g.:: 
    2574 
    2575            from sqlalchemy import table, column, select 
    2576 
    2577            t = table("t", column("c1"), column("c2")) 
    2578 
    2579            ins = t.insert().values({"c1": "x", "c2": "y"}).cte() 
    2580 
    2581            stmt = select(t).add_cte(ins) 
    2582 
    2583        Would render: 
    2584 
    2585        .. sourcecode:: sql 
    2586 
    2587            WITH anon_1 AS ( 
    2588                INSERT INTO t (c1, c2) VALUES (:param_1, :param_2) 
    2589            ) 
    2590            SELECT t.c1, t.c2 
    2591            FROM t 
    2592 
    2593        Above, the "anon_1" CTE is not referenced in the SELECT 
    2594        statement, however still accomplishes the task of running an INSERT 
    2595        statement. 
    2596 
    2597        Similarly in a DML-related context, using the PostgreSQL 
    2598        :class:`_postgresql.Insert` construct to generate an "upsert":: 
    2599 
    2600            from sqlalchemy import table, column 
    2601            from sqlalchemy.dialects.postgresql import insert 
    2602 
    2603            t = table("t", column("c1"), column("c2")) 
    2604 
    2605            delete_statement_cte = t.delete().where(t.c.c1 < 1).cte("deletions") 
    2606 
    2607            insert_stmt = insert(t).values({"c1": 1, "c2": 2}) 
    2608            update_statement = insert_stmt.on_conflict_do_update( 
    2609                index_elements=[t.c.c1], 
    2610                set_={ 
    2611                    "c1": insert_stmt.excluded.c1, 
    2612                    "c2": insert_stmt.excluded.c2, 
    2613                }, 
    2614            ).add_cte(delete_statement_cte) 
    2615 
    2616            print(update_statement) 
    2617 
    2618        The above statement renders as: 
    2619 
    2620        .. sourcecode:: sql 
    2621 
    2622            WITH deletions AS ( 
    2623                DELETE FROM t WHERE t.c1 < %(c1_1)s 
    2624            ) 
    2625            INSERT INTO t (c1, c2) VALUES (%(c1)s, %(c2)s) 
    2626            ON CONFLICT (c1) DO UPDATE SET c1 = excluded.c1, c2 = excluded.c2 
    2627 
    2628        .. versionadded:: 1.4.21 
    2629 
    2630        :param \*ctes: zero or more :class:`.CTE` constructs. 
    2631 
    2632         .. versionchanged:: 2.0  Multiple CTE instances are accepted 
    2633 
    2634        :param nest_here: if True, the given CTE or CTEs will be rendered 
    2635         as though they specified the :paramref:`.HasCTE.cte.nesting` flag 
    2636         to ``True`` when they were added to this :class:`.HasCTE`. 
    2637         Assuming the given CTEs are not referenced in an outer-enclosing 
    2638         statement as well, the CTEs given should render at the level of 
    2639         this statement when this flag is given. 
    2640 
    2641         .. versionadded:: 2.0 
    2642 
    2643         .. seealso:: 
    2644 
    2645            :paramref:`.HasCTE.cte.nesting` 
    2646 
    2647 
    2648        """  # noqa: E501 
    2649        opt = _CTEOpts(nest_here) 
    2650        for cte in ctes: 
    2651            cte = coercions.expect(roles.IsCTERole, cte) 
    2652            self._independent_ctes += (cte,) 
    2653            self._independent_ctes_opts += (opt,) 
    2654        return self 
    2655 
    2656    def cte( 
    2657        self, 
    2658        name: Optional[str] = None, 
    2659        recursive: bool = False, 
    2660        nesting: bool = False, 
    2661    ) -> CTE: 
    2662        r"""Return a new :class:`_expression.CTE`, 
    2663        or Common Table Expression instance. 
    2664 
    2665        Common table expressions are a SQL standard whereby SELECT 
    2666        statements can draw upon secondary statements specified along 
    2667        with the primary statement, using a clause called "WITH". 
    2668        Special semantics regarding UNION can also be employed to 
    2669        allow "recursive" queries, where a SELECT statement can draw 
    2670        upon the set of rows that have previously been selected. 
    2671 
    2672        CTEs can also be applied to DML constructs UPDATE, INSERT 
    2673        and DELETE on some databases, both as a source of CTE rows 
    2674        when combined with RETURNING, as well as a consumer of 
    2675        CTE rows. 
    2676 
    2677        SQLAlchemy detects :class:`_expression.CTE` objects, which are treated 
    2678        similarly to :class:`_expression.Alias` objects, as special elements 
    2679        to be delivered to the FROM clause of the statement as well 
    2680        as to a WITH clause at the top of the statement. 
    2681 
    2682        For special prefixes such as PostgreSQL "MATERIALIZED" and 
    2683        "NOT MATERIALIZED", the :meth:`_expression.CTE.prefix_with` 
    2684        method may be 
    2685        used to establish these. 
    2686 
    2687        :param name: name given to the common table expression.  Like 
    2688         :meth:`_expression.FromClause.alias`, the name can be left as 
    2689         ``None`` in which case an anonymous symbol will be used at query 
    2690         compile time. 
    2691        :param recursive: if ``True``, will render ``WITH RECURSIVE``. 
    2692         A recursive common table expression is intended to be used in 
    2693         conjunction with UNION ALL in order to derive rows 
    2694         from those already selected. 
    2695        :param nesting: if ``True``, will render the CTE locally to the 
    2696         statement in which it is referenced.   For more complex scenarios, 
    2697         the :meth:`.HasCTE.add_cte` method using the 
    2698         :paramref:`.HasCTE.add_cte.nest_here` 
    2699         parameter may also be used to more carefully 
    2700         control the exact placement of a particular CTE. 
    2701 
    2702         .. versionadded:: 1.4.24 
    2703 
    2704         .. seealso:: 
    2705 
    2706            :meth:`.HasCTE.add_cte` 
    2707 
    2708        The following examples include two from PostgreSQL's documentation at 
    2709        https://www.postgresql.org/docs/current/static/queries-with.html, 
    2710        as well as additional examples. 
    2711 
    2712        Example 1, non recursive:: 
    2713 
    2714            from sqlalchemy import ( 
    2715                Table, 
    2716                Column, 
    2717                String, 
    2718                Integer, 
    2719                MetaData, 
    2720                select, 
    2721                func, 
    2722            ) 
    2723 
    2724            metadata = MetaData() 
    2725 
    2726            orders = Table( 
    2727                "orders", 
    2728                metadata, 
    2729                Column("region", String), 
    2730                Column("amount", Integer), 
    2731                Column("product", String), 
    2732                Column("quantity", Integer), 
    2733            ) 
    2734 
    2735            regional_sales = ( 
    2736                select(orders.c.region, func.sum(orders.c.amount).label("total_sales")) 
    2737                .group_by(orders.c.region) 
    2738                .cte("regional_sales") 
    2739            ) 
    2740 
    2741 
    2742            top_regions = ( 
    2743                select(regional_sales.c.region) 
    2744                .where( 
    2745                    regional_sales.c.total_sales 
    2746                    > select(func.sum(regional_sales.c.total_sales) / 10) 
    2747                ) 
    2748                .cte("top_regions") 
    2749            ) 
    2750 
    2751            statement = ( 
    2752                select( 
    2753                    orders.c.region, 
    2754                    orders.c.product, 
    2755                    func.sum(orders.c.quantity).label("product_units"), 
    2756                    func.sum(orders.c.amount).label("product_sales"), 
    2757                ) 
    2758                .where(orders.c.region.in_(select(top_regions.c.region))) 
    2759                .group_by(orders.c.region, orders.c.product) 
    2760            ) 
    2761 
    2762            result = conn.execute(statement).fetchall() 
    2763 
    2764        Example 2, WITH RECURSIVE:: 
    2765 
    2766            from sqlalchemy import ( 
    2767                Table, 
    2768                Column, 
    2769                String, 
    2770                Integer, 
    2771                MetaData, 
    2772                select, 
    2773                func, 
    2774            ) 
    2775 
    2776            metadata = MetaData() 
    2777 
    2778            parts = Table( 
    2779                "parts", 
    2780                metadata, 
    2781                Column("part", String), 
    2782                Column("sub_part", String), 
    2783                Column("quantity", Integer), 
    2784            ) 
    2785 
    2786            included_parts = ( 
    2787                select(parts.c.sub_part, parts.c.part, parts.c.quantity) 
    2788                .where(parts.c.part == "our part") 
    2789                .cte(recursive=True) 
    2790            ) 
    2791 
    2792 
    2793            incl_alias = included_parts.alias() 
    2794            parts_alias = parts.alias() 
    2795            included_parts = included_parts.union_all( 
    2796                select( 
    2797                    parts_alias.c.sub_part, parts_alias.c.part, parts_alias.c.quantity 
    2798                ).where(parts_alias.c.part == incl_alias.c.sub_part) 
    2799            ) 
    2800 
    2801            statement = select( 
    2802                included_parts.c.sub_part, 
    2803                func.sum(included_parts.c.quantity).label("total_quantity"), 
    2804            ).group_by(included_parts.c.sub_part) 
    2805 
    2806            result = conn.execute(statement).fetchall() 
    2807 
    2808        Example 3, an upsert using UPDATE and INSERT with CTEs:: 
    2809 
    2810            from datetime import date 
    2811            from sqlalchemy import ( 
    2812                MetaData, 
    2813                Table, 
    2814                Column, 
    2815                Integer, 
    2816                Date, 
    2817                select, 
    2818                literal, 
    2819                and_, 
    2820                exists, 
    2821            ) 
    2822 
    2823            metadata = MetaData() 
    2824 
    2825            visitors = Table( 
    2826                "visitors", 
    2827                metadata, 
    2828                Column("product_id", Integer, primary_key=True), 
    2829                Column("date", Date, primary_key=True), 
    2830                Column("count", Integer), 
    2831            ) 
    2832 
    2833            # add 5 visitors for the product_id == 1 
    2834            product_id = 1 
    2835            day = date.today() 
    2836            count = 5 
    2837 
    2838            update_cte = ( 
    2839                visitors.update() 
    2840                .where( 
    2841                    and_(visitors.c.product_id == product_id, visitors.c.date == day) 
    2842                ) 
    2843                .values(count=visitors.c.count + count) 
    2844                .returning(literal(1)) 
    2845                .cte("update_cte") 
    2846            ) 
    2847 
    2848            upsert = visitors.insert().from_select( 
    2849                [visitors.c.product_id, visitors.c.date, visitors.c.count], 
    2850                select(literal(product_id), literal(day), literal(count)).where( 
    2851                    ~exists(update_cte.select()) 
    2852                ), 
    2853            ) 
    2854 
    2855            connection.execute(upsert) 
    2856 
    2857        Example 4, Nesting CTE (SQLAlchemy 1.4.24 and above):: 
    2858 
    2859            value_a = select(literal("root").label("n")).cte("value_a") 
    2860 
    2861            # A nested CTE with the same name as the root one 
    2862            value_a_nested = select(literal("nesting").label("n")).cte( 
    2863                "value_a", nesting=True 
    2864            ) 
    2865 
    2866            # Nesting CTEs takes ascendency locally 
    2867            # over the CTEs at a higher level 
    2868            value_b = select(value_a_nested.c.n).cte("value_b") 
    2869 
    2870            value_ab = select(value_a.c.n.label("a"), value_b.c.n.label("b")) 
    2871 
    2872        The above query will render the second CTE nested inside the first, 
    2873        shown with inline parameters below as: 
    2874 
    2875        .. sourcecode:: sql 
    2876 
    2877            WITH 
    2878                value_a AS 
    2879                    (SELECT 'root' AS n), 
    2880                value_b AS 
    2881                    (WITH value_a AS 
    2882                        (SELECT 'nesting' AS n) 
    2883                    SELECT value_a.n AS n FROM value_a) 
    2884            SELECT value_a.n AS a, value_b.n AS b 
    2885            FROM value_a, value_b 
    2886 
    2887        The same CTE can be set up using the :meth:`.HasCTE.add_cte` method 
    2888        as follows (SQLAlchemy 2.0 and above):: 
    2889 
    2890            value_a = select(literal("root").label("n")).cte("value_a") 
    2891 
    2892            # A nested CTE with the same name as the root one 
    2893            value_a_nested = select(literal("nesting").label("n")).cte("value_a") 
    2894 
    2895            # Nesting CTEs takes ascendency locally 
    2896            # over the CTEs at a higher level 
    2897            value_b = ( 
    2898                select(value_a_nested.c.n) 
    2899                .add_cte(value_a_nested, nest_here=True) 
    2900                .cte("value_b") 
    2901            ) 
    2902 
    2903            value_ab = select(value_a.c.n.label("a"), value_b.c.n.label("b")) 
    2904 
    2905        Example 5, Non-Linear CTE (SQLAlchemy 1.4.28 and above):: 
    2906 
    2907            edge = Table( 
    2908                "edge", 
    2909                metadata, 
    2910                Column("id", Integer, primary_key=True), 
    2911                Column("left", Integer), 
    2912                Column("right", Integer), 
    2913            ) 
    2914 
    2915            root_node = select(literal(1).label("node")).cte("nodes", recursive=True) 
    2916 
    2917            left_edge = select(edge.c.left).join( 
    2918                root_node, edge.c.right == root_node.c.node 
    2919            ) 
    2920            right_edge = select(edge.c.right).join( 
    2921                root_node, edge.c.left == root_node.c.node 
    2922            ) 
    2923 
    2924            subgraph_cte = root_node.union(left_edge, right_edge) 
    2925 
    2926            subgraph = select(subgraph_cte) 
    2927 
    2928        The above query will render 2 UNIONs inside the recursive CTE: 
    2929 
    2930        .. sourcecode:: sql 
    2931 
    2932            WITH RECURSIVE nodes(node) AS ( 
    2933                    SELECT 1 AS node 
    2934                UNION 
    2935                    SELECT edge."left" AS "left" 
    2936                    FROM edge JOIN nodes ON edge."right" = nodes.node 
    2937                UNION 
    2938                    SELECT edge."right" AS "right" 
    2939                    FROM edge JOIN nodes ON edge."left" = nodes.node 
    2940            ) 
    2941            SELECT nodes.node FROM nodes 
    2942 
    2943        .. seealso:: 
    2944 
    2945            :meth:`_orm.Query.cte` - ORM version of 
    2946            :meth:`_expression.HasCTE.cte`. 
    2947 
    2948        """  # noqa: E501 
    2949        return CTE._construct( 
    2950            self, name=name, recursive=recursive, nesting=nesting 
    2951        ) 
    2952 
    2953 
    2954class Subquery(AliasedReturnsRows): 
    2955    """Represent a subquery of a SELECT. 
    2956 
    2957    A :class:`.Subquery` is created by invoking the 
    2958    :meth:`_expression.SelectBase.subquery` method, or for convenience the 
    2959    :meth:`_expression.SelectBase.alias` method, on any 
    2960    :class:`_expression.SelectBase` subclass 
    2961    which includes :class:`_expression.Select`, 
    2962    :class:`_expression.CompoundSelect`, and 
    2963    :class:`_expression.TextualSelect`.  As rendered in a FROM clause, 
    2964    it represents the 
    2965    body of the SELECT statement inside of parenthesis, followed by the usual 
    2966    "AS <somename>" that defines all "alias" objects. 
    2967 
    2968    The :class:`.Subquery` object is very similar to the 
    2969    :class:`_expression.Alias` 
    2970    object and can be used in an equivalent way.    The difference between 
    2971    :class:`_expression.Alias` and :class:`.Subquery` is that 
    2972    :class:`_expression.Alias` always 
    2973    contains a :class:`_expression.FromClause` object whereas 
    2974    :class:`.Subquery` 
    2975    always contains a :class:`_expression.SelectBase` object. 
    2976 
    2977    .. versionadded:: 1.4 The :class:`.Subquery` class was added which now 
    2978       serves the purpose of providing an aliased version of a SELECT 
    2979       statement. 
    2980 
    2981    """ 
    2982 
    2983    __visit_name__ = "subquery" 
    2984 
    2985    _is_subquery = True 
    2986 
    2987    inherit_cache = True 
    2988 
    2989    element: SelectBase 
    2990 
    2991    @classmethod 
    2992    def _factory( 
    2993        cls, selectable: SelectBase, name: Optional[str] = None 
    2994    ) -> Subquery: 
    2995        """Return a :class:`.Subquery` object.""" 
    2996 
    2997        return coercions.expect( 
    2998            roles.SelectStatementRole, selectable 
    2999        ).subquery(name=name) 
    3000 
    3001    @util.deprecated( 
    3002        "1.4", 
    3003        "The :meth:`.Subquery.as_scalar` method, which was previously " 
    3004        "``Alias.as_scalar()`` prior to version 1.4, is deprecated and " 
    3005        "will be removed in a future release; Please use the " 
    3006        ":meth:`_expression.Select.scalar_subquery` method of the " 
    3007        ":func:`_expression.select` " 
    3008        "construct before constructing a subquery object, or with the ORM " 
    3009        "use the :meth:`_query.Query.scalar_subquery` method.", 
    3010    ) 
    3011    def as_scalar(self) -> ScalarSelect[Any]: 
    3012        return self.element.set_label_style(LABEL_STYLE_NONE).scalar_subquery() 
    3013 
    3014 
    3015class FromGrouping(GroupedElement, FromClause): 
    3016    """Represent a grouping of a FROM clause""" 
    3017 
    3018    _traverse_internals: _TraverseInternalsType = [ 
    3019        ("element", InternalTraversal.dp_clauseelement) 
    3020    ] 
    3021 
    3022    element: FromClause 
    3023 
    3024    def __init__(self, element: FromClause): 
    3025        self.element = coercions.expect(roles.FromClauseRole, element) 
    3026 
    3027    @util.ro_non_memoized_property 
    3028    def columns( 
    3029        self, 
    3030    ) -> ReadOnlyColumnCollection[str, KeyedColumnElement[Any]]: 
    3031        return self.element.columns 
    3032 
    3033    @util.ro_non_memoized_property 
    3034    def c(self) -> ReadOnlyColumnCollection[str, KeyedColumnElement[Any]]: 
    3035        return self.element.columns 
    3036 
    3037    @property 
    3038    def primary_key(self) -> Iterable[NamedColumn[Any]]: 
    3039        return self.element.primary_key 
    3040 
    3041    @property 
    3042    def foreign_keys(self) -> Iterable[ForeignKey]: 
    3043        return self.element.foreign_keys 
    3044 
    3045    def is_derived_from(self, fromclause: Optional[FromClause]) -> bool: 
    3046        return self.element.is_derived_from(fromclause) 
    3047 
    3048    def alias( 
    3049        self, name: Optional[str] = None, flat: bool = False 
    3050    ) -> NamedFromGrouping: 
    3051        return NamedFromGrouping(self.element.alias(name=name, flat=flat)) 
    3052 
    3053    def _anonymous_fromclause(self, **kw: Any) -> FromGrouping: 
    3054        return FromGrouping(self.element._anonymous_fromclause(**kw)) 
    3055 
    3056    @util.ro_non_memoized_property 
    3057    def _hide_froms(self) -> Iterable[FromClause]: 
    3058        return self.element._hide_froms 
    3059 
    3060    @util.ro_non_memoized_property 
    3061    def _from_objects(self) -> List[FromClause]: 
    3062        return self.element._from_objects 
    3063 
    3064    def __getstate__(self) -> Dict[str, FromClause]: 
    3065        return {"element": self.element} 
    3066 
    3067    def __setstate__(self, state: Dict[str, FromClause]) -> None: 
    3068        self.element = state["element"] 
    3069 
    3070    if TYPE_CHECKING: 
    3071 
    3072        def self_group( 
    3073            self, against: Optional[OperatorType] = None 
    3074        ) -> Self: ... 
    3075 
    3076 
    3077class NamedFromGrouping(FromGrouping, NamedFromClause): 
    3078    """represent a grouping of a named FROM clause 
    3079 
    3080    .. versionadded:: 2.0 
    3081 
    3082    """ 
    3083 
    3084    inherit_cache = True 
    3085 
    3086    if TYPE_CHECKING: 
    3087 
    3088        def self_group( 
    3089            self, against: Optional[OperatorType] = None 
    3090        ) -> Self: ... 
    3091 
    3092 
    3093class TableClause(roles.DMLTableRole, Immutable, NamedFromClause): 
    3094    """Represents a minimal "table" construct. 
    3095 
    3096    This is a lightweight table object that has only a name, a 
    3097    collection of columns, which are typically produced 
    3098    by the :func:`_expression.column` function, and a schema:: 
    3099 
    3100        from sqlalchemy import table, column 
    3101 
    3102        user = table( 
    3103            "user", 
    3104            column("id"), 
    3105            column("name"), 
    3106            column("description"), 
    3107        ) 
    3108 
    3109    The :class:`_expression.TableClause` construct serves as the base for 
    3110    the more commonly used :class:`_schema.Table` object, providing 
    3111    the usual set of :class:`_expression.FromClause` services including 
    3112    the ``.c.`` collection and statement generation methods. 
    3113 
    3114    It does **not** provide all the additional schema-level services 
    3115    of :class:`_schema.Table`, including constraints, references to other 
    3116    tables, or support for :class:`_schema.MetaData`-level services. 
    3117    It's useful 
    3118    on its own as an ad-hoc construct used to generate quick SQL 
    3119    statements when a more fully fledged :class:`_schema.Table` 
    3120    is not on hand. 
    3121 
    3122    """ 
    3123 
    3124    __visit_name__ = "table" 
    3125 
    3126    _traverse_internals: _TraverseInternalsType = [ 
    3127        ( 
    3128            "columns", 
    3129            InternalTraversal.dp_fromclause_canonical_column_collection, 
    3130        ), 
    3131        ("name", InternalTraversal.dp_string), 
    3132        ("schema", InternalTraversal.dp_string), 
    3133    ] 
    3134 
    3135    _is_table = True 
    3136 
    3137    fullname: str 
    3138 
    3139    implicit_returning = False 
    3140    """:class:`_expression.TableClause` 
    3141    doesn't support having a primary key or column 
    3142    -level defaults, so implicit returning doesn't apply.""" 
    3143 
    3144    _columns: DedupeColumnCollection[ColumnClause[Any]] 
    3145 
    3146    @util.ro_memoized_property 
    3147    def _autoincrement_column(self) -> Optional[ColumnClause[Any]]: 
    3148        """No PK or default support so no autoincrement column.""" 
    3149        return None 
    3150 
    3151    def __init__(self, name: str, *columns: ColumnClause[Any], **kw: Any): 
    3152        super().__init__() 
    3153        self.name = name 
    3154        self._columns = DedupeColumnCollection()  # type: ignore[unused-ignore] 
    3155        self.primary_key = ColumnSet()  # type: ignore 
    3156        self.foreign_keys = set()  # type: ignore 
    3157        for c in columns: 
    3158            self.append_column(c) 
    3159 
    3160        schema = kw.pop("schema", None) 
    3161        if schema is not None: 
    3162            self.schema = schema 
    3163        if self.schema is not None: 
    3164            self.fullname = "%s.%s" % (self.schema, self.name) 
    3165        else: 
    3166            self.fullname = self.name 
    3167        if kw: 
    3168            raise exc.ArgumentError("Unsupported argument(s): %s" % list(kw)) 
    3169 
    3170    if TYPE_CHECKING: 
    3171 
    3172        @util.ro_non_memoized_property 
    3173        def columns( 
    3174            self, 
    3175        ) -> ReadOnlyColumnCollection[str, ColumnClause[Any]]: ... 
    3176 
    3177        @util.ro_non_memoized_property 
    3178        def c(self) -> ReadOnlyColumnCollection[str, ColumnClause[Any]]: ... 
    3179 
    3180    def __str__(self) -> str: 
    3181        if self.schema is not None: 
    3182            return self.schema + "." + self.name 
    3183        else: 
    3184            return self.name 
    3185 
    3186    def _refresh_for_new_column(self, column: ColumnElement[Any]) -> None: 
    3187        pass 
    3188 
    3189    @util.ro_memoized_property 
    3190    def description(self) -> str: 
    3191        return self.name 
    3192 
    3193    def _insert_col_impl( 
    3194        self, 
    3195        c: ColumnClause[Any], 
    3196        *, 
    3197        index: Optional[int] = None, 
    3198    ) -> None: 
    3199        existing = c.table 
    3200        if existing is not None and existing is not self: 
    3201            raise exc.ArgumentError( 
    3202                "column object '%s' already assigned to table '%s'" 
    3203                % (c.key, existing) 
    3204            ) 
    3205        self._columns.add(c, index=index) 
    3206        c.table = self 
    3207 
    3208    def append_column(self, c: ColumnClause[Any]) -> None: 
    3209        self._insert_col_impl(c) 
    3210 
    3211    def insert_column(self, c: ColumnClause[Any], index: int) -> None: 
    3212        self._insert_col_impl(c, index=index) 
    3213 
    3214    @util.preload_module("sqlalchemy.sql.dml") 
    3215    def insert(self) -> util.preloaded.sql_dml.Insert: 
    3216        """Generate an :class:`_sql.Insert` construct against this 
    3217        :class:`_expression.TableClause`. 
    3218 
    3219        E.g.:: 
    3220 
    3221            table.insert().values(name="foo") 
    3222 
    3223        See :func:`_expression.insert` for argument and usage information. 
    3224 
    3225        """ 
    3226 
    3227        return util.preloaded.sql_dml.Insert(self) 
    3228 
    3229    @util.preload_module("sqlalchemy.sql.dml") 
    3230    def update(self) -> Update: 
    3231        """Generate an :func:`_expression.update` construct against this 
    3232        :class:`_expression.TableClause`. 
    3233 
    3234        E.g.:: 
    3235 
    3236            table.update().where(table.c.id == 7).values(name="foo") 
    3237 
    3238        See :func:`_expression.update` for argument and usage information. 
    3239 
    3240        """ 
    3241        return util.preloaded.sql_dml.Update( 
    3242            self, 
    3243        ) 
    3244 
    3245    @util.preload_module("sqlalchemy.sql.dml") 
    3246    def delete(self) -> Delete: 
    3247        """Generate a :func:`_expression.delete` construct against this 
    3248        :class:`_expression.TableClause`. 
    3249 
    3250        E.g.:: 
    3251 
    3252            table.delete().where(table.c.id == 7) 
    3253 
    3254        See :func:`_expression.delete` for argument and usage information. 
    3255 
    3256        """ 
    3257        return util.preloaded.sql_dml.Delete(self) 
    3258 
    3259    @util.ro_non_memoized_property 
    3260    def _from_objects(self) -> List[FromClause]: 
    3261        return [self] 
    3262 
    3263 
    3264ForUpdateParameter = Union["ForUpdateArg", None, bool, Dict[str, Any]] 
    3265 
    3266 
    3267class ForUpdateArg(ClauseElement): 
    3268    _traverse_internals: _TraverseInternalsType = [ 
    3269        ("of", InternalTraversal.dp_clauseelement_list), 
    3270        ("nowait", InternalTraversal.dp_boolean), 
    3271        ("read", InternalTraversal.dp_boolean), 
    3272        ("skip_locked", InternalTraversal.dp_boolean), 
    3273        ("key_share", InternalTraversal.dp_boolean), 
    3274    ] 
    3275 
    3276    of: Optional[Sequence[ClauseElement]] 
    3277    nowait: bool 
    3278    read: bool 
    3279    skip_locked: bool 
    3280 
    3281    @classmethod 
    3282    def _from_argument( 
    3283        cls, with_for_update: ForUpdateParameter 
    3284    ) -> Optional[ForUpdateArg]: 
    3285        if isinstance(with_for_update, ForUpdateArg): 
    3286            return with_for_update 
    3287        elif with_for_update in (None, False): 
    3288            return None 
    3289        elif with_for_update is True: 
    3290            return ForUpdateArg() 
    3291        else: 
    3292            return ForUpdateArg(**cast("Dict[str, Any]", with_for_update)) 
    3293 
    3294    def __eq__(self, other: Any) -> bool: 
    3295        return ( 
    3296            isinstance(other, ForUpdateArg) 
    3297            and other.nowait == self.nowait 
    3298            and other.read == self.read 
    3299            and other.skip_locked == self.skip_locked 
    3300            and other.key_share == self.key_share 
    3301            and other.of is self.of 
    3302        ) 
    3303 
    3304    def __ne__(self, other: Any) -> bool: 
    3305        return not self.__eq__(other) 
    3306 
    3307    def __hash__(self) -> int: 
    3308        return id(self) 
    3309 
    3310    def __init__( 
    3311        self, 
    3312        *, 
    3313        nowait: bool = False, 
    3314        read: bool = False, 
    3315        of: Optional[_ForUpdateOfArgument] = None, 
    3316        skip_locked: bool = False, 
    3317        key_share: bool = False, 
    3318    ): 
    3319        """Represents arguments specified to 
    3320        :meth:`_expression.Select.for_update`. 
    3321 
    3322        """ 
    3323 
    3324        self.nowait = nowait 
    3325        self.read = read 
    3326        self.skip_locked = skip_locked 
    3327        self.key_share = key_share 
    3328        if of is not None: 
    3329            self.of = [ 
    3330                coercions.expect(roles.ColumnsClauseRole, elem) 
    3331                for elem in util.to_list(of) 
    3332            ] 
    3333        else: 
    3334            self.of = None 
    3335 
    3336 
    3337class Values(roles.InElementRole, HasCTE, Generative, LateralFromClause): 
    3338    """Represent a ``VALUES`` construct that can be used as a FROM element 
    3339    in a statement. 
    3340 
    3341    The :class:`_expression.Values` object is created from the 
    3342    :func:`_expression.values` function. 
    3343 
    3344    .. versionadded:: 1.4 
    3345 
    3346    """ 
    3347 
    3348    __visit_name__ = "values" 
    3349 
    3350    _data: Tuple[Sequence[Tuple[Any, ...]], ...] = () 
    3351 
    3352    _unnamed: bool 
    3353    _traverse_internals: _TraverseInternalsType = [ 
    3354        ("_column_args", InternalTraversal.dp_clauseelement_list), 
    3355        ("_data", InternalTraversal.dp_dml_multi_values), 
    3356        ("name", InternalTraversal.dp_string), 
    3357        ("literal_binds", InternalTraversal.dp_boolean), 
    3358    ] + HasCTE._has_ctes_traverse_internals 
    3359 
    3360    name_cte_columns = True 
    3361 
    3362    def __init__( 
    3363        self, 
    3364        *columns: ColumnClause[Any], 
    3365        name: Optional[str] = None, 
    3366        literal_binds: bool = False, 
    3367    ): 
    3368        super().__init__() 
    3369        self._column_args = columns 
    3370 
    3371        if name is None: 
    3372            self._unnamed = True 
    3373            self.name = _anonymous_label.safe_construct(id(self), "anon") 
    3374        else: 
    3375            self._unnamed = False 
    3376            self.name = name 
    3377        self.literal_binds = literal_binds 
    3378        self.named_with_column = not self._unnamed 
    3379 
    3380    @property 
    3381    def _column_types(self) -> List[TypeEngine[Any]]: 
    3382        return [col.type for col in self._column_args] 
    3383 
    3384    @util.ro_non_memoized_property 
    3385    def _all_selected_columns(self) -> _SelectIterable: 
    3386        return self._column_args 
    3387 
    3388    @_generative 
    3389    def alias(self, name: Optional[str] = None, flat: bool = False) -> Self: 
    3390        """Return a new :class:`_expression.Values` 
    3391        construct that is a copy of this 
    3392        one with the given name. 
    3393 
    3394        This method is a VALUES-specific specialization of the 
    3395        :meth:`_expression.FromClause.alias` method. 
    3396 
    3397        .. seealso:: 
    3398 
    3399            :ref:`tutorial_using_aliases` 
    3400 
    3401            :func:`_expression.alias` 
    3402 
    3403        """ 
    3404        non_none_name: str 
    3405 
    3406        if name is None: 
    3407            non_none_name = _anonymous_label.safe_construct(id(self), "anon") 
    3408        else: 
    3409            non_none_name = name 
    3410 
    3411        self.name = non_none_name 
    3412        self.named_with_column = True 
    3413        self._unnamed = False 
    3414        return self 
    3415 
    3416    @_generative 
    3417    def lateral(self, name: Optional[str] = None) -> Self: 
    3418        """Return a new :class:`_expression.Values` with the lateral flag set, 
    3419        so that 
    3420        it renders as LATERAL. 
    3421 
    3422        .. seealso:: 
    3423 
    3424            :func:`_expression.lateral` 
    3425 
    3426        """ 
    3427        non_none_name: str 
    3428 
    3429        if name is None: 
    3430            non_none_name = self.name 
    3431        else: 
    3432            non_none_name = name 
    3433 
    3434        self._is_lateral = True 
    3435        self.name = non_none_name 
    3436        self._unnamed = False 
    3437        return self 
    3438 
    3439    @_generative 
    3440    def data(self, values: Sequence[Tuple[Any, ...]]) -> Self: 
    3441        """Return a new :class:`_expression.Values` construct, 
    3442        adding the given data to the data list. 
    3443 
    3444        E.g.:: 
    3445 
    3446            my_values = my_values.data([(1, "value 1"), (2, "value2")]) 
    3447 
    3448        :param values: a sequence (i.e. list) of tuples that map to the 
    3449         column expressions given in the :class:`_expression.Values` 
    3450         constructor. 
    3451 
    3452        """ 
    3453 
    3454        self._data += (values,) 
    3455        return self 
    3456 
    3457    def scalar_values(self) -> ScalarValues: 
    3458        """Returns a scalar ``VALUES`` construct that can be used as a 
    3459        COLUMN element in a statement. 
    3460 
    3461        .. versionadded:: 2.0.0b4 
    3462 
    3463        """ 
    3464        return ScalarValues(self._column_args, self._data, self.literal_binds) 
    3465 
    3466    def _populate_column_collection( 
    3467        self, 
    3468        columns: ColumnCollection[str, KeyedColumnElement[Any]], 
    3469        primary_key: ColumnSet, 
    3470        foreign_keys: Set[KeyedColumnElement[Any]], 
    3471    ) -> None: 
    3472        for c in self._column_args: 
    3473            if c.table is not None and c.table is not self: 
    3474                _, c = c._make_proxy( 
    3475                    self, primary_key=primary_key, foreign_keys=foreign_keys 
    3476                ) 
    3477            else: 
    3478                # if the column was used in other contexts, ensure 
    3479                # no memoizations of other FROM clauses. 
    3480                # see test_values.py -> test_auto_proxy_select_direct_col 
    3481                c._reset_memoizations() 
    3482            columns.add(c) 
    3483            c.table = self 
    3484 
    3485    @util.ro_non_memoized_property 
    3486    def _from_objects(self) -> List[FromClause]: 
    3487        return [self] 
    3488 
    3489 
    3490class ScalarValues(roles.InElementRole, GroupedElement, ColumnElement[Any]): 
    3491    """Represent a scalar ``VALUES`` construct that can be used as a 
    3492    COLUMN element in a statement. 
    3493 
    3494    The :class:`_expression.ScalarValues` object is created from the 
    3495    :meth:`_expression.Values.scalar_values` method. It's also 
    3496    automatically generated when a :class:`_expression.Values` is used in 
    3497    an ``IN`` or ``NOT IN`` condition. 
    3498 
    3499    .. versionadded:: 2.0.0b4 
    3500 
    3501    """ 
    3502 
    3503    __visit_name__ = "scalar_values" 
    3504 
    3505    _traverse_internals: _TraverseInternalsType = [ 
    3506        ("_column_args", InternalTraversal.dp_clauseelement_list), 
    3507        ("_data", InternalTraversal.dp_dml_multi_values), 
    3508        ("literal_binds", InternalTraversal.dp_boolean), 
    3509    ] 
    3510 
    3511    def __init__( 
    3512        self, 
    3513        columns: Sequence[ColumnClause[Any]], 
    3514        data: Tuple[Sequence[Tuple[Any, ...]], ...], 
    3515        literal_binds: bool, 
    3516    ): 
    3517        super().__init__() 
    3518        self._column_args = columns 
    3519        self._data = data 
    3520        self.literal_binds = literal_binds 
    3521 
    3522    @property 
    3523    def _column_types(self) -> List[TypeEngine[Any]]: 
    3524        return [col.type for col in self._column_args] 
    3525 
    3526    def __clause_element__(self) -> ScalarValues: 
    3527        return self 
    3528 
    3529    if TYPE_CHECKING: 
    3530 
    3531        def self_group( 
    3532            self, against: Optional[OperatorType] = None 
    3533        ) -> Self: ... 
    3534 
    3535        def _ungroup(self) -> ColumnElement[Any]: ... 
    3536 
    3537 
    3538class SelectBase( 
    3539    roles.SelectStatementRole, 
    3540    roles.DMLSelectRole, 
    3541    roles.CompoundElementRole, 
    3542    roles.InElementRole, 
    3543    HasCTE, 
    3544    SupportsCloneAnnotations, 
    3545    Selectable, 
    3546): 
    3547    """Base class for SELECT statements. 
    3548 
    3549 
    3550    This includes :class:`_expression.Select`, 
    3551    :class:`_expression.CompoundSelect` and 
    3552    :class:`_expression.TextualSelect`. 
    3553 
    3554 
    3555    """ 
    3556 
    3557    _is_select_base = True 
    3558    is_select = True 
    3559 
    3560    _label_style: SelectLabelStyle = LABEL_STYLE_NONE 
    3561 
    3562    def _refresh_for_new_column(self, column: ColumnElement[Any]) -> None: 
    3563        self._reset_memoizations() 
    3564 
    3565    @util.ro_non_memoized_property 
    3566    def selected_columns( 
    3567        self, 
    3568    ) -> ColumnCollection[str, ColumnElement[Any]]: 
    3569        """A :class:`_expression.ColumnCollection` 
    3570        representing the columns that 
    3571        this SELECT statement or similar construct returns in its result set. 
    3572 
    3573        This collection differs from the :attr:`_expression.FromClause.columns` 
    3574        collection of a :class:`_expression.FromClause` in that the columns 
    3575        within this collection cannot be directly nested inside another SELECT 
    3576        statement; a subquery must be applied first which provides for the 
    3577        necessary parenthesization required by SQL. 
    3578 
    3579        .. note:: 
    3580 
    3581            The :attr:`_sql.SelectBase.selected_columns` collection does not 
    3582            include expressions established in the columns clause using the 
    3583            :func:`_sql.text` construct; these are silently omitted from the 
    3584            collection. To use plain textual column expressions inside of a 
    3585            :class:`_sql.Select` construct, use the :func:`_sql.literal_column` 
    3586            construct. 
    3587 
    3588        .. seealso:: 
    3589 
    3590            :attr:`_sql.Select.selected_columns` 
    3591 
    3592        .. versionadded:: 1.4 
    3593 
    3594        """ 
    3595        raise NotImplementedError() 
    3596 
    3597    def _generate_fromclause_column_proxies( 
    3598        self, 
    3599        subquery: FromClause, 
    3600        columns: ColumnCollection[str, KeyedColumnElement[Any]], 
    3601        primary_key: ColumnSet, 
    3602        foreign_keys: Set[KeyedColumnElement[Any]], 
    3603        *, 
    3604        proxy_compound_columns: Optional[ 
    3605            Iterable[Sequence[ColumnElement[Any]]] 
    3606        ] = None, 
    3607    ) -> None: 
    3608        raise NotImplementedError() 
    3609 
    3610    @util.ro_non_memoized_property 
    3611    def _all_selected_columns(self) -> _SelectIterable: 
    3612        """A sequence of expressions that correspond to what is rendered 
    3613        in the columns clause, including :class:`_sql.TextClause` 
    3614        constructs. 
    3615 
    3616        .. versionadded:: 1.4.12 
    3617 
    3618        .. seealso:: 
    3619 
    3620            :attr:`_sql.SelectBase.exported_columns` 
    3621 
    3622        """ 
    3623        raise NotImplementedError() 
    3624 
    3625    @property 
    3626    def exported_columns( 
    3627        self, 
    3628    ) -> ReadOnlyColumnCollection[str, ColumnElement[Any]]: 
    3629        """A :class:`_expression.ColumnCollection` 
    3630        that represents the "exported" 
    3631        columns of this :class:`_expression.Selectable`, not including 
    3632        :class:`_sql.TextClause` constructs. 
    3633 
    3634        The "exported" columns for a :class:`_expression.SelectBase` 
    3635        object are synonymous 
    3636        with the :attr:`_expression.SelectBase.selected_columns` collection. 
    3637 
    3638        .. versionadded:: 1.4 
    3639 
    3640        .. seealso:: 
    3641 
    3642            :attr:`_expression.Select.exported_columns` 
    3643 
    3644            :attr:`_expression.Selectable.exported_columns` 
    3645 
    3646            :attr:`_expression.FromClause.exported_columns` 
    3647 
    3648 
    3649        """ 
    3650        return self.selected_columns.as_readonly() 
    3651 
    3652    def get_label_style(self) -> SelectLabelStyle: 
    3653        """ 
    3654        Retrieve the current label style. 
    3655 
    3656        Implemented by subclasses. 
    3657 
    3658        """ 
    3659        raise NotImplementedError() 
    3660 
    3661    def set_label_style(self, style: SelectLabelStyle) -> Self: 
    3662        """Return a new selectable with the specified label style. 
    3663 
    3664        Implemented by subclasses. 
    3665 
    3666        """ 
    3667 
    3668        raise NotImplementedError() 
    3669 
    3670    def _scalar_type(self) -> TypeEngine[Any]: 
    3671        raise NotImplementedError() 
    3672 
    3673    @util.deprecated( 
    3674        "1.4", 
    3675        "The :meth:`_expression.SelectBase.as_scalar` " 
    3676        "method is deprecated and will be " 
    3677        "removed in a future release.  Please refer to " 
    3678        ":meth:`_expression.SelectBase.scalar_subquery`.", 
    3679    ) 
    3680    def as_scalar(self) -> ScalarSelect[Any]: 
    3681        return self.scalar_subquery() 
    3682 
    3683    def exists(self) -> Exists: 
    3684        """Return an :class:`_sql.Exists` representation of this selectable, 
    3685        which can be used as a column expression. 
    3686 
    3687        The returned object is an instance of :class:`_sql.Exists`. 
    3688 
    3689        .. seealso:: 
    3690 
    3691            :func:`_sql.exists` 
    3692 
    3693            :ref:`tutorial_exists` - in the :term:`2.0 style` tutorial. 
    3694 
    3695        .. versionadded:: 1.4 
    3696 
    3697        """ 
    3698        return Exists(self) 
    3699 
    3700    def scalar_subquery(self) -> ScalarSelect[Any]: 
    3701        """Return a 'scalar' representation of this selectable, which can be 
    3702        used as a column expression. 
    3703 
    3704        The returned object is an instance of :class:`_sql.ScalarSelect`. 
    3705 
    3706        Typically, a select statement which has only one column in its columns 
    3707        clause is eligible to be used as a scalar expression.  The scalar 
    3708        subquery can then be used in the WHERE clause or columns clause of 
    3709        an enclosing SELECT. 
    3710 
    3711        Note that the scalar subquery differentiates from the FROM-level 
    3712        subquery that can be produced using the 
    3713        :meth:`_expression.SelectBase.subquery` 
    3714        method. 
    3715 
    3716        .. versionchanged:: 1.4 - the ``.as_scalar()`` method was renamed to 
    3717           :meth:`_expression.SelectBase.scalar_subquery`. 
    3718 
    3719        .. seealso:: 
    3720 
    3721            :ref:`tutorial_scalar_subquery` - in the 2.0 tutorial 
    3722 
    3723        """ 
    3724        if self._label_style is not LABEL_STYLE_NONE: 
    3725            self = self.set_label_style(LABEL_STYLE_NONE) 
    3726 
    3727        return ScalarSelect(self) 
    3728 
    3729    def label(self, name: Optional[str]) -> Label[Any]: 
    3730        """Return a 'scalar' representation of this selectable, embedded as a 
    3731        subquery with a label. 
    3732 
    3733        .. seealso:: 
    3734 
    3735            :meth:`_expression.SelectBase.scalar_subquery`. 
    3736 
    3737        """ 
    3738        return self.scalar_subquery().label(name) 
    3739 
    3740    def lateral(self, name: Optional[str] = None) -> LateralFromClause: 
    3741        """Return a LATERAL alias of this :class:`_expression.Selectable`. 
    3742 
    3743        The return value is the :class:`_expression.Lateral` construct also 
    3744        provided by the top-level :func:`_expression.lateral` function. 
    3745 
    3746        .. seealso:: 
    3747 
    3748            :ref:`tutorial_lateral_correlation` -  overview of usage. 
    3749 
    3750        """ 
    3751        return Lateral._factory(self, name) 
    3752 
    3753    def subquery(self, name: Optional[str] = None) -> Subquery: 
    3754        """Return a subquery of this :class:`_expression.SelectBase`. 
    3755 
    3756        A subquery is from a SQL perspective a parenthesized, named 
    3757        construct that can be placed in the FROM clause of another 
    3758        SELECT statement. 
    3759 
    3760        Given a SELECT statement such as:: 
    3761 
    3762            stmt = select(table.c.id, table.c.name) 
    3763 
    3764        The above statement might look like: 
    3765 
    3766        .. sourcecode:: sql 
    3767 
    3768            SELECT table.id, table.name FROM table 
    3769 
    3770        The subquery form by itself renders the same way, however when 
    3771        embedded into the FROM clause of another SELECT statement, it becomes 
    3772        a named sub-element:: 
    3773 
    3774            subq = stmt.subquery() 
    3775            new_stmt = select(subq) 
    3776 
    3777        The above renders as: 
    3778 
    3779        .. sourcecode:: sql 
    3780 
    3781            SELECT anon_1.id, anon_1.name 
    3782            FROM (SELECT table.id, table.name FROM table) AS anon_1 
    3783 
    3784        Historically, :meth:`_expression.SelectBase.subquery` 
    3785        is equivalent to calling 
    3786        the :meth:`_expression.FromClause.alias` 
    3787        method on a FROM object; however, 
    3788        as a :class:`_expression.SelectBase` 
    3789        object is not directly  FROM object, 
    3790        the :meth:`_expression.SelectBase.subquery` 
    3791        method provides clearer semantics. 
    3792 
    3793        .. versionadded:: 1.4 
    3794 
    3795        """ 
    3796 
    3797        return Subquery._construct( 
    3798            self._ensure_disambiguated_names(), name=name 
    3799        ) 
    3800 
    3801    @util.preload_module("sqlalchemy.sql.ddl") 
    3802    def into( 
    3803        self, 
    3804        target: str, 
    3805        *, 
    3806        metadata: Optional["MetaData"] = None, 
    3807        schema: Optional[str] = None, 
    3808        temporary: bool = False, 
    3809        if_not_exists: bool = False, 
    3810    ) -> CreateTableAs: 
    3811        """Create a :class:`_schema.CreateTableAs` construct from this SELECT. 
    3812 
    3813        This method provides a convenient way to create a ``CREATE TABLE ... 
    3814        AS`` statement from a SELECT, as well as compound SELECTs like UNION. 
    3815        The new table will be created with columns matching the SELECT list. 
    3816 
    3817        Supported on all included backends, the construct emits 
    3818        ``CREATE TABLE...AS`` for all backends except SQL Server, which instead 
    3819        emits a ``SELECT..INTO`` statement. 
    3820 
    3821        e.g.:: 
    3822 
    3823            from sqlalchemy import select 
    3824 
    3825            # Create a new table from a SELECT 
    3826            stmt = ( 
    3827                select(users.c.id, users.c.name) 
    3828                .where(users.c.status == "active") 
    3829                .into("active_users") 
    3830            ) 
    3831 
    3832            with engine.begin() as conn: 
    3833                conn.execute(stmt) 
    3834 
    3835            # With optional flags 
    3836            stmt = ( 
    3837                select(users.c.id) 
    3838                .where(users.c.status == "inactive") 
    3839                .into("inactive_users", schema="analytics", if_not_exists=True) 
    3840            ) 
    3841 
    3842        .. versionadded:: 2.1 
    3843 
    3844        :param target: Name of the table to create as a string. Must be 
    3845            unqualified; use the ``schema`` parameter for qualification. 
    3846 
    3847        :param metadata: :class:`_schema.MetaData`, optional 
    3848            If provided, the :class:`_schema.Table` object available via the 
    3849            :attr:`.table` attribute will be associated with this 
    3850            :class:`.MetaData`.  Otherwise, a new, empty :class:`.MetaData` 
    3851            is created. 
    3852 
    3853        :param schema: Optional schema name for the new table. 
    3854 
    3855        :param temporary: If True, create a temporary table where supported 
    3856 
    3857        :param if_not_exists: If True, add IF NOT EXISTS clause where supported 
    3858 
    3859        :return: A :class:`_schema.CreateTableAs` construct. 
    3860 
    3861        .. seealso:: 
    3862 
    3863            :ref:`tutorial_create_table_as` - in the :ref:`unified_tutorial` 
    3864 
    3865            :class:`_schema.CreateTableAs` 
    3866 
    3867        """ 
    3868        sql_ddl = util.preloaded.sql_ddl 
    3869 
    3870        return sql_ddl.CreateTableAs( 
    3871            self, 
    3872            target, 
    3873            metadata=metadata, 
    3874            schema=schema, 
    3875            temporary=temporary, 
    3876            if_not_exists=if_not_exists, 
    3877        ) 
    3878 
    3879    def _ensure_disambiguated_names(self) -> Self: 
    3880        """Ensure that the names generated by this selectbase will be 
    3881        disambiguated in some way, if possible. 
    3882 
    3883        """ 
    3884 
    3885        raise NotImplementedError() 
    3886 
    3887    def alias( 
    3888        self, name: Optional[str] = None, flat: bool = False 
    3889    ) -> Subquery: 
    3890        """Return a named subquery against this 
    3891        :class:`_expression.SelectBase`. 
    3892 
    3893        For a :class:`_expression.SelectBase` (as opposed to a 
    3894        :class:`_expression.FromClause`), 
    3895        this returns a :class:`.Subquery` object which behaves mostly the 
    3896        same as the :class:`_expression.Alias` object that is used with a 
    3897        :class:`_expression.FromClause`. 
    3898 
    3899        .. versionchanged:: 1.4 The :meth:`_expression.SelectBase.alias` 
    3900           method is now 
    3901           a synonym for the :meth:`_expression.SelectBase.subquery` method. 
    3902 
    3903        """ 
    3904        return self.subquery(name=name) 
    3905 
    3906 
    3907_SB = TypeVar("_SB", bound=SelectBase) 
    3908 
    3909 
    3910class SelectStatementGrouping(GroupedElement, SelectBase, Generic[_SB]): 
    3911    """Represent a grouping of a :class:`_expression.SelectBase`. 
    3912 
    3913    This differs from :class:`.Subquery` in that we are still 
    3914    an "inner" SELECT statement, this is strictly for grouping inside of 
    3915    compound selects. 
    3916 
    3917    """ 
    3918 
    3919    __visit_name__ = "select_statement_grouping" 
    3920    _traverse_internals: _TraverseInternalsType = [ 
    3921        ("element", InternalTraversal.dp_clauseelement) 
    3922    ] + SupportsCloneAnnotations._clone_annotations_traverse_internals 
    3923 
    3924    _is_select_container = True 
    3925 
    3926    element: _SB 
    3927 
    3928    def __init__(self, element: _SB) -> None: 
    3929        self.element = cast( 
    3930            _SB, coercions.expect(roles.SelectStatementRole, element) 
    3931        ) 
    3932 
    3933    def _ensure_disambiguated_names(self) -> SelectStatementGrouping[_SB]: 
    3934        new_element = self.element._ensure_disambiguated_names() 
    3935        if new_element is not self.element: 
    3936            return SelectStatementGrouping(new_element) 
    3937        else: 
    3938            return self 
    3939 
    3940    def get_label_style(self) -> SelectLabelStyle: 
    3941        return self.element.get_label_style() 
    3942 
    3943    def set_label_style( 
    3944        self, label_style: SelectLabelStyle 
    3945    ) -> SelectStatementGrouping[_SB]: 
    3946        return SelectStatementGrouping( 
    3947            self.element.set_label_style(label_style) 
    3948        ) 
    3949 
    3950    @property 
    3951    def select_statement(self) -> _SB: 
    3952        return self.element 
    3953 
    3954    def self_group(self, against: Optional[OperatorType] = None) -> Self: 
    3955        return self 
    3956 
    3957    if TYPE_CHECKING: 
    3958 
    3959        def _ungroup(self) -> _SB: ... 
    3960 
    3961    # def _generate_columns_plus_names( 
    3962    #    self, anon_for_dupe_key: bool 
    3963    # ) -> List[Tuple[str, str, str, ColumnElement[Any], bool]]: 
    3964    #    return self.element._generate_columns_plus_names(anon_for_dupe_key) 
    3965 
    3966    def _generate_fromclause_column_proxies( 
    3967        self, 
    3968        subquery: FromClause, 
    3969        columns: ColumnCollection[str, KeyedColumnElement[Any]], 
    3970        primary_key: ColumnSet, 
    3971        foreign_keys: Set[KeyedColumnElement[Any]], 
    3972        *, 
    3973        proxy_compound_columns: Optional[ 
    3974            Iterable[Sequence[ColumnElement[Any]]] 
    3975        ] = None, 
    3976    ) -> None: 
    3977        self.element._generate_fromclause_column_proxies( 
    3978            subquery, 
    3979            columns, 
    3980            proxy_compound_columns=proxy_compound_columns, 
    3981            primary_key=primary_key, 
    3982            foreign_keys=foreign_keys, 
    3983        ) 
    3984 
    3985    @util.ro_non_memoized_property 
    3986    def _all_selected_columns(self) -> _SelectIterable: 
    3987        return self.element._all_selected_columns 
    3988 
    3989    @util.ro_non_memoized_property 
    3990    def selected_columns(self) -> ColumnCollection[str, ColumnElement[Any]]: 
    3991        """A :class:`_expression.ColumnCollection` 
    3992        representing the columns that 
    3993        the embedded SELECT statement returns in its result set, not including 
    3994        :class:`_sql.TextClause` constructs. 
    3995 
    3996        .. versionadded:: 1.4 
    3997 
    3998        .. seealso:: 
    3999 
    4000            :attr:`_sql.Select.selected_columns` 
    4001 
    4002        """ 
    4003        return self.element.selected_columns 
    4004 
    4005    @util.ro_non_memoized_property 
    4006    def _from_objects(self) -> List[FromClause]: 
    4007        return self.element._from_objects 
    4008 
    4009    def add_cte(self, *ctes: CTE, nest_here: bool = False) -> Self: 
    4010        # SelectStatementGrouping not generative: has no attribute '_generate' 
    4011        raise NotImplementedError 
    4012 
    4013 
    4014class GenerativeSelect(DialectKWArgs, SelectBase, Generative): 
    4015    """Base class for SELECT statements where additional elements can be 
    4016    added. 
    4017 
    4018    This serves as the base for :class:`_expression.Select` and 
    4019    :class:`_expression.CompoundSelect` 
    4020    where elements such as ORDER BY, GROUP BY can be added and column 
    4021    rendering can be controlled.  Compare to 
    4022    :class:`_expression.TextualSelect`, which, 
    4023    while it subclasses :class:`_expression.SelectBase` 
    4024    and is also a SELECT construct, 
    4025    represents a fixed textual string which cannot be altered at this level, 
    4026    only wrapped as a subquery. 
    4027 
    4028    """ 
    4029 
    4030    _order_by_clauses: Tuple[ColumnElement[Any], ...] = () 
    4031    _group_by_clauses: Tuple[ColumnElement[Any], ...] = () 
    4032    _limit_clause: Optional[ColumnElement[Any]] = None 
    4033    _offset_clause: Optional[ColumnElement[Any]] = None 
    4034    _fetch_clause: Optional[ColumnElement[Any]] = None 
    4035    _fetch_clause_options: Optional[Dict[str, bool]] = None 
    4036    _for_update_arg: Optional[ForUpdateArg] = None 
    4037 
    4038    def __init__(self, _label_style: SelectLabelStyle = LABEL_STYLE_DEFAULT): 
    4039        self._label_style = _label_style 
    4040 
    4041    @_generative 
    4042    def with_for_update( 
    4043        self, 
    4044        *, 
    4045        nowait: bool = False, 
    4046        read: bool = False, 
    4047        of: Optional[_ForUpdateOfArgument] = None, 
    4048        skip_locked: bool = False, 
    4049        key_share: bool = False, 
    4050    ) -> Self: 
    4051        """Specify a ``FOR UPDATE`` clause for this 
    4052        :class:`_expression.GenerativeSelect`. 
    4053 
    4054        E.g.:: 
    4055 
    4056            stmt = select(table).with_for_update(nowait=True) 
    4057 
    4058        On a database like PostgreSQL or Oracle Database, the above would 
    4059        render a statement like: 
    4060 
    4061        .. sourcecode:: sql 
    4062 
    4063            SELECT table.a, table.b FROM table FOR UPDATE NOWAIT 
    4064 
    4065        on other backends, the ``nowait`` option is ignored and instead 
    4066        would produce: 
    4067 
    4068        .. sourcecode:: sql 
    4069 
    4070            SELECT table.a, table.b FROM table FOR UPDATE 
    4071 
    4072        When called with no arguments, the statement will render with 
    4073        the suffix ``FOR UPDATE``.   Additional arguments can then be 
    4074        provided which allow for common database-specific 
    4075        variants. 
    4076 
    4077        :param nowait: boolean; will render ``FOR UPDATE NOWAIT`` on Oracle 
    4078         Database and PostgreSQL dialects. 
    4079 
    4080        :param read: boolean; will render ``LOCK IN SHARE MODE`` on MySQL, 
    4081         ``FOR SHARE`` on PostgreSQL.  On PostgreSQL, when combined with 
    4082         ``nowait``, will render ``FOR SHARE NOWAIT``. 
    4083 
    4084        :param of: SQL expression or list of SQL expression elements, 
    4085         (typically :class:`_schema.Column` objects or a compatible expression, 
    4086         for some backends may also be a table expression) which will render 
    4087         into a ``FOR UPDATE OF`` clause; supported by PostgreSQL, Oracle 
    4088         Database, some MySQL versions and possibly others. May render as a 
    4089         table or as a column depending on backend. 
    4090 
    4091        :param skip_locked: boolean, will render ``FOR UPDATE SKIP LOCKED`` on 
    4092         Oracle Database and PostgreSQL dialects or ``FOR SHARE SKIP LOCKED`` 
    4093         if ``read=True`` is also specified. 
    4094 
    4095        :param key_share: boolean, will render ``FOR NO KEY UPDATE``, 
    4096         or if combined with ``read=True`` will render ``FOR KEY SHARE``, 
    4097         on the PostgreSQL dialect. 
    4098 
    4099        """ 
    4100        self._for_update_arg = ForUpdateArg( 
    4101            nowait=nowait, 
    4102            read=read, 
    4103            of=of, 
    4104            skip_locked=skip_locked, 
    4105            key_share=key_share, 
    4106        ) 
    4107        return self 
    4108 
    4109    def get_label_style(self) -> SelectLabelStyle: 
    4110        """ 
    4111        Retrieve the current label style. 
    4112 
    4113        .. versionadded:: 1.4 
    4114 
    4115        """ 
    4116        return self._label_style 
    4117 
    4118    def set_label_style(self, style: SelectLabelStyle) -> Self: 
    4119        """Return a new selectable with the specified label style. 
    4120 
    4121        There are three "label styles" available, 
    4122        :attr:`_sql.SelectLabelStyle.LABEL_STYLE_DISAMBIGUATE_ONLY`, 
    4123        :attr:`_sql.SelectLabelStyle.LABEL_STYLE_TABLENAME_PLUS_COL`, and 
    4124        :attr:`_sql.SelectLabelStyle.LABEL_STYLE_NONE`.   The default style is 
    4125        :attr:`_sql.SelectLabelStyle.LABEL_STYLE_DISAMBIGUATE_ONLY`. 
    4126 
    4127        In modern SQLAlchemy, there is not generally a need to change the 
    4128        labeling style, as per-expression labels are more effectively used by 
    4129        making use of the :meth:`_sql.ColumnElement.label` method. In past 
    4130        versions, :data:`_sql.LABEL_STYLE_TABLENAME_PLUS_COL` was used to 
    4131        disambiguate same-named columns from different tables, aliases, or 
    4132        subqueries; the newer :data:`_sql.LABEL_STYLE_DISAMBIGUATE_ONLY` now 
    4133        applies labels only to names that conflict with an existing name so 
    4134        that the impact of this labeling is minimal. 
    4135 
    4136        The rationale for disambiguation is mostly so that all column 
    4137        expressions are available from a given :attr:`_sql.FromClause.c` 
    4138        collection when a subquery is created. 
    4139 
    4140        .. versionadded:: 1.4 - the 
    4141            :meth:`_sql.GenerativeSelect.set_label_style` method replaces the 
    4142            previous combination of ``.apply_labels()``, ``.with_labels()`` and 
    4143            ``use_labels=True`` methods and/or parameters. 
    4144 
    4145        .. seealso:: 
    4146 
    4147            :data:`_sql.LABEL_STYLE_DISAMBIGUATE_ONLY` 
    4148 
    4149            :data:`_sql.LABEL_STYLE_TABLENAME_PLUS_COL` 
    4150 
    4151            :data:`_sql.LABEL_STYLE_NONE` 
    4152 
    4153            :data:`_sql.LABEL_STYLE_DEFAULT` 
    4154 
    4155        """ 
    4156        if self._label_style is not style: 
    4157            self = self._generate() 
    4158            self._label_style = style 
    4159        return self 
    4160 
    4161    @property 
    4162    def _group_by_clause(self) -> ClauseList: 
    4163        """ClauseList access to group_by_clauses for legacy dialects""" 
    4164        return ClauseList._construct_raw( 
    4165            operators.comma_op, self._group_by_clauses 
    4166        ) 
    4167 
    4168    @property 
    4169    def _order_by_clause(self) -> ClauseList: 
    4170        """ClauseList access to order_by_clauses for legacy dialects""" 
    4171        return ClauseList._construct_raw( 
    4172            operators.comma_op, self._order_by_clauses 
    4173        ) 
    4174 
    4175    def _offset_or_limit_clause( 
    4176        self, 
    4177        element: _LimitOffsetType, 
    4178        name: Optional[str] = None, 
    4179        type_: Optional[_TypeEngineArgument[int]] = None, 
    4180    ) -> ColumnElement[Any]: 
    4181        """Convert the given value to an "offset or limit" clause. 
    4182 
    4183        This handles incoming integers and converts to an expression; if 
    4184        an expression is already given, it is passed through. 
    4185 
    4186        """ 
    4187        return coercions.expect( 
    4188            roles.LimitOffsetRole, element, name=name, type_=type_ 
    4189        ) 
    4190 
    4191    @overload 
    4192    def _offset_or_limit_clause_asint( 
    4193        self, clause: ColumnElement[Any], attrname: str 
    4194    ) -> NoReturn: ... 
    4195 
    4196    @overload 
    4197    def _offset_or_limit_clause_asint( 
    4198        self, clause: Optional[_OffsetLimitParam], attrname: str 
    4199    ) -> Optional[int]: ... 
    4200 
    4201    def _offset_or_limit_clause_asint( 
    4202        self, clause: Optional[ColumnElement[Any]], attrname: str 
    4203    ) -> Union[NoReturn, Optional[int]]: 
    4204        """Convert the "offset or limit" clause of a select construct to an 
    4205        integer. 
    4206 
    4207        This is only possible if the value is stored as a simple bound 
    4208        parameter. Otherwise, a compilation error is raised. 
    4209 
    4210        """ 
    4211        if clause is None: 
    4212            return None 
    4213        try: 
    4214            value = clause._limit_offset_value 
    4215        except AttributeError as err: 
    4216            raise exc.CompileError( 
    4217                "This SELECT structure does not use a simple " 
    4218                "integer value for %s" % attrname 
    4219            ) from err 
    4220        else: 
    4221            return util.asint(value) 
    4222 
    4223    @property 
    4224    def _limit(self) -> Optional[int]: 
    4225        """Get an integer value for the limit.  This should only be used 
    4226        by code that cannot support a limit as a BindParameter or 
    4227        other custom clause as it will throw an exception if the limit 
    4228        isn't currently set to an integer. 
    4229 
    4230        """ 
    4231        return self._offset_or_limit_clause_asint(self._limit_clause, "limit") 
    4232 
    4233    def _simple_int_clause(self, clause: ClauseElement) -> bool: 
    4234        """True if the clause is a simple integer, False 
    4235        if it is not present or is a SQL expression. 
    4236        """ 
    4237        return isinstance(clause, _OffsetLimitParam) 
    4238 
    4239    @property 
    4240    def _offset(self) -> Optional[int]: 
    4241        """Get an integer value for the offset.  This should only be used 
    4242        by code that cannot support an offset as a BindParameter or 
    4243        other custom clause as it will throw an exception if the 
    4244        offset isn't currently set to an integer. 
    4245 
    4246        """ 
    4247        return self._offset_or_limit_clause_asint( 
    4248            self._offset_clause, "offset" 
    4249        ) 
    4250 
    4251    @property 
    4252    def _has_row_limiting_clause(self) -> bool: 
    4253        return ( 
    4254            self._limit_clause is not None 
    4255            or self._offset_clause is not None 
    4256            or self._fetch_clause is not None 
    4257        ) 
    4258 
    4259    @_generative 
    4260    def limit(self, limit: _LimitOffsetType) -> Self: 
    4261        """Return a new selectable with the given LIMIT criterion 
    4262        applied. 
    4263 
    4264        This is a numerical value which usually renders as a ``LIMIT`` 
    4265        expression in the resulting select.  Backends that don't 
    4266        support ``LIMIT`` will attempt to provide similar 
    4267        functionality. 
    4268 
    4269        .. note:: 
    4270 
    4271           The :meth:`_sql.GenerativeSelect.limit` method will replace 
    4272           any clause applied with :meth:`_sql.GenerativeSelect.fetch`. 
    4273 
    4274        :param limit: an integer LIMIT parameter, or a SQL expression 
    4275         that provides an integer result. Pass ``None`` to reset it. 
    4276 
    4277        .. seealso:: 
    4278 
    4279           :meth:`_sql.GenerativeSelect.fetch` 
    4280 
    4281           :meth:`_sql.GenerativeSelect.offset` 
    4282 
    4283        """ 
    4284 
    4285        self._fetch_clause = self._fetch_clause_options = None 
    4286        self._limit_clause = self._offset_or_limit_clause(limit) 
    4287        return self 
    4288 
    4289    @_generative 
    4290    def fetch( 
    4291        self, 
    4292        count: _LimitOffsetType, 
    4293        with_ties: bool = False, 
    4294        percent: bool = False, 
    4295        **dialect_kw: Any, 
    4296    ) -> Self: 
    4297        r"""Return a new selectable with the given FETCH FIRST criterion 
    4298        applied. 
    4299 
    4300        This is a numeric value which usually renders as ``FETCH {FIRST | NEXT} 
    4301        [ count ] {ROW | ROWS} {ONLY | WITH TIES}`` expression in the resulting 
    4302        select. This functionality is is currently implemented for Oracle 
    4303        Database, PostgreSQL, MSSQL. 
    4304 
    4305        Use :meth:`_sql.GenerativeSelect.offset` to specify the offset. 
    4306 
    4307        .. note:: 
    4308 
    4309           The :meth:`_sql.GenerativeSelect.fetch` method will replace 
    4310           any clause applied with :meth:`_sql.GenerativeSelect.limit`. 
    4311 
    4312        .. versionadded:: 1.4 
    4313 
    4314        :param count: an integer COUNT parameter, or a SQL expression 
    4315         that provides an integer result. When ``percent=True`` this will 
    4316         represent the percentage of rows to return, not the absolute value. 
    4317         Pass ``None`` to reset it. 
    4318 
    4319        :param with_ties: When ``True``, the WITH TIES option is used 
    4320         to return any additional rows that tie for the last place in the 
    4321         result set according to the ``ORDER BY`` clause. The 
    4322         ``ORDER BY`` may be mandatory in this case. Defaults to ``False`` 
    4323 
    4324        :param percent: When ``True``, ``count`` represents the percentage 
    4325         of the total number of selected rows to return. Defaults to ``False`` 
    4326 
    4327        :param \**dialect_kw: Additional dialect-specific keyword arguments 
    4328         may be accepted by dialects. 
    4329 
    4330         .. versionadded:: 2.0.41 
    4331 
    4332        .. seealso:: 
    4333 
    4334           :meth:`_sql.GenerativeSelect.limit` 
    4335 
    4336           :meth:`_sql.GenerativeSelect.offset` 
    4337 
    4338        """ 
    4339        self._validate_dialect_kwargs(dialect_kw) 
    4340        self._limit_clause = None 
    4341        if count is None: 
    4342            self._fetch_clause = self._fetch_clause_options = None 
    4343        else: 
    4344            self._fetch_clause = self._offset_or_limit_clause(count) 
    4345            self._fetch_clause_options = { 
    4346                "with_ties": with_ties, 
    4347                "percent": percent, 
    4348            } 
    4349        return self 
    4350 
    4351    @_generative 
    4352    def offset(self, offset: _LimitOffsetType) -> Self: 
    4353        """Return a new selectable with the given OFFSET criterion 
    4354        applied. 
    4355 
    4356 
    4357        This is a numeric value which usually renders as an ``OFFSET`` 
    4358        expression in the resulting select.  Backends that don't 
    4359        support ``OFFSET`` will attempt to provide similar 
    4360        functionality. 
    4361 
    4362        :param offset: an integer OFFSET parameter, or a SQL expression 
    4363         that provides an integer result. Pass ``None`` to reset it. 
    4364 
    4365        .. seealso:: 
    4366 
    4367           :meth:`_sql.GenerativeSelect.limit` 
    4368 
    4369           :meth:`_sql.GenerativeSelect.fetch` 
    4370 
    4371        """ 
    4372 
    4373        self._offset_clause = self._offset_or_limit_clause(offset) 
    4374        return self 
    4375 
    4376    @_generative 
    4377    @util.preload_module("sqlalchemy.sql.util") 
    4378    def slice( 
    4379        self, 
    4380        start: int, 
    4381        stop: int, 
    4382    ) -> Self: 
    4383        """Apply LIMIT / OFFSET to this statement based on a slice. 
    4384 
    4385        The start and stop indices behave like the argument to Python's 
    4386        built-in :func:`range` function. This method provides an 
    4387        alternative to using ``LIMIT``/``OFFSET`` to get a slice of the 
    4388        query. 
    4389 
    4390        For example, :: 
    4391 
    4392            stmt = select(User).order_by(User.id).slice(1, 3) 
    4393 
    4394        renders as 
    4395 
    4396        .. sourcecode:: sql 
    4397 
    4398           SELECT users.id AS users_id, 
    4399                  users.name AS users_name 
    4400           FROM users ORDER BY users.id 
    4401           LIMIT ? OFFSET ? 
    4402           (2, 1) 
    4403 
    4404        .. note:: 
    4405 
    4406           The :meth:`_sql.GenerativeSelect.slice` method will replace 
    4407           any clause applied with :meth:`_sql.GenerativeSelect.fetch`. 
    4408 
    4409        .. versionadded:: 1.4  Added the :meth:`_sql.GenerativeSelect.slice` 
    4410           method generalized from the ORM. 
    4411 
    4412        .. seealso:: 
    4413 
    4414           :meth:`_sql.GenerativeSelect.limit` 
    4415 
    4416           :meth:`_sql.GenerativeSelect.offset` 
    4417 
    4418           :meth:`_sql.GenerativeSelect.fetch` 
    4419 
    4420        """ 
    4421        sql_util = util.preloaded.sql_util 
    4422        self._fetch_clause = self._fetch_clause_options = None 
    4423        self._limit_clause, self._offset_clause = sql_util._make_slice( 
    4424            self._limit_clause, self._offset_clause, start, stop 
    4425        ) 
    4426        return self 
    4427 
    4428    @_generative 
    4429    def order_by( 
    4430        self, 
    4431        __first: Union[ 
    4432            Literal[None, _NoArg.NO_ARG], 
    4433            _ColumnExpressionOrStrLabelArgument[Any], 
    4434        ] = _NoArg.NO_ARG, 
    4435        /, 
    4436        *clauses: _ColumnExpressionOrStrLabelArgument[Any], 
    4437    ) -> Self: 
    4438        r"""Return a new selectable with the given list of ORDER BY 
    4439        criteria applied. 
    4440 
    4441        e.g.:: 
    4442 
    4443            stmt = select(table).order_by(table.c.id, table.c.name) 
    4444 
    4445        Calling this method multiple times is equivalent to calling it once 
    4446        with all the clauses concatenated. All existing ORDER BY criteria may 
    4447        be cancelled by passing ``None`` by itself.  New ORDER BY criteria may 
    4448        then be added by invoking :meth:`_orm.Query.order_by` again, e.g.:: 
    4449 
    4450            # will erase all ORDER BY and ORDER BY new_col alone 
    4451            stmt = stmt.order_by(None).order_by(new_col) 
    4452 
    4453        :param \*clauses: a series of :class:`_expression.ColumnElement` 
    4454         constructs which will be used to generate an ORDER BY clause. 
    4455 
    4456         Alternatively, an individual entry may also be the string name of a 
    4457         label located elsewhere in the columns clause of the statement which 
    4458         will be matched and rendered in a backend-specific way based on 
    4459         context; see :ref:`tutorial_order_by_label` for background on string 
    4460         label matching in ORDER BY and GROUP BY expressions. 
    4461 
    4462        .. seealso:: 
    4463 
    4464            :ref:`tutorial_order_by` - in the :ref:`unified_tutorial` 
    4465 
    4466            :ref:`tutorial_order_by_label` - in the :ref:`unified_tutorial` 
    4467 
    4468        """ 
    4469 
    4470        if not clauses and __first is None: 
    4471            self._order_by_clauses = () 
    4472        elif __first is not _NoArg.NO_ARG: 
    4473            self._order_by_clauses += tuple( 
    4474                coercions.expect( 
    4475                    roles.OrderByRole, clause, apply_propagate_attrs=self 
    4476                ) 
    4477                for clause in (__first,) + clauses 
    4478            ) 
    4479        return self 
    4480 
    4481    @_generative 
    4482    def group_by( 
    4483        self, 
    4484        __first: Union[ 
    4485            Literal[None, _NoArg.NO_ARG], 
    4486            _ColumnExpressionOrStrLabelArgument[Any], 
    4487        ] = _NoArg.NO_ARG, 
    4488        /, 
    4489        *clauses: _ColumnExpressionOrStrLabelArgument[Any], 
    4490    ) -> Self: 
    4491        r"""Return a new selectable with the given list of GROUP BY 
    4492        criterion applied. 
    4493 
    4494        All existing GROUP BY settings can be suppressed by passing ``None``. 
    4495 
    4496        e.g.:: 
    4497 
    4498            stmt = select(table.c.name, func.max(table.c.stat)).group_by(table.c.name) 
    4499 
    4500        :param \*clauses: a series of :class:`_expression.ColumnElement` 
    4501         constructs which will be used to generate an GROUP BY clause. 
    4502 
    4503         Alternatively, an individual entry may also be the string name of a 
    4504         label located elsewhere in the columns clause of the statement which 
    4505         will be matched and rendered in a backend-specific way based on 
    4506         context; see :ref:`tutorial_order_by_label` for background on string 
    4507         label matching in ORDER BY and GROUP BY expressions. 
    4508 
    4509        .. seealso:: 
    4510 
    4511            :ref:`tutorial_group_by_w_aggregates` - in the 
    4512            :ref:`unified_tutorial` 
    4513 
    4514            :ref:`tutorial_order_by_label` - in the :ref:`unified_tutorial` 
    4515 
    4516        """  # noqa: E501 
    4517 
    4518        if not clauses and __first is None: 
    4519            self._group_by_clauses = () 
    4520        elif __first is not _NoArg.NO_ARG: 
    4521            self._group_by_clauses += tuple( 
    4522                coercions.expect( 
    4523                    roles.GroupByRole, clause, apply_propagate_attrs=self 
    4524                ) 
    4525                for clause in (__first,) + clauses 
    4526            ) 
    4527        return self 
    4528 
    4529 
    4530@CompileState.plugin_for("default", "compound_select") 
    4531class CompoundSelectState(CompileState): 
    4532    @util.memoized_property 
    4533    def _label_resolve_dict( 
    4534        self, 
    4535    ) -> Tuple[ 
    4536        Dict[str, ColumnElement[Any]], 
    4537        Dict[str, ColumnElement[Any]], 
    4538        Dict[str, ColumnElement[Any]], 
    4539    ]: 
    4540        # TODO: this is hacky and slow 
    4541        hacky_subquery = self.statement.subquery() 
    4542        hacky_subquery.named_with_column = False 
    4543        d = {c.key: c for c in hacky_subquery.c} 
    4544        return d, d, d 
    4545 
    4546 
    4547class _CompoundSelectKeyword(Enum): 
    4548    UNION = "UNION" 
    4549    UNION_ALL = "UNION ALL" 
    4550    EXCEPT = "EXCEPT" 
    4551    EXCEPT_ALL = "EXCEPT ALL" 
    4552    INTERSECT = "INTERSECT" 
    4553    INTERSECT_ALL = "INTERSECT ALL" 
    4554 
    4555 
    4556class CompoundSelect( 
    4557    HasCompileState, GenerativeSelect, TypedReturnsRows[Unpack[_Ts]] 
    4558): 
    4559    """Forms the basis of ``UNION``, ``UNION ALL``, and other 
    4560    SELECT-based set operations. 
    4561 
    4562 
    4563    .. seealso:: 
    4564 
    4565        :func:`_expression.union` 
    4566 
    4567        :func:`_expression.union_all` 
    4568 
    4569        :func:`_expression.intersect` 
    4570 
    4571        :func:`_expression.intersect_all` 
    4572 
    4573        :func:`_expression.except` 
    4574 
    4575        :func:`_expression.except_all` 
    4576 
    4577    """ 
    4578 
    4579    __visit_name__ = "compound_select" 
    4580 
    4581    _traverse_internals: _TraverseInternalsType = ( 
    4582        [ 
    4583            ("selects", InternalTraversal.dp_clauseelement_list), 
    4584            ("_limit_clause", InternalTraversal.dp_clauseelement), 
    4585            ("_offset_clause", InternalTraversal.dp_clauseelement), 
    4586            ("_fetch_clause", InternalTraversal.dp_clauseelement), 
    4587            ("_fetch_clause_options", InternalTraversal.dp_plain_dict), 
    4588            ("_order_by_clauses", InternalTraversal.dp_clauseelement_list), 
    4589            ("_group_by_clauses", InternalTraversal.dp_clauseelement_list), 
    4590            ("_for_update_arg", InternalTraversal.dp_clauseelement), 
    4591            ("keyword", InternalTraversal.dp_string), 
    4592        ] 
    4593        + SupportsCloneAnnotations._clone_annotations_traverse_internals 
    4594        + HasCTE._has_ctes_traverse_internals 
    4595        + DialectKWArgs._dialect_kwargs_traverse_internals 
    4596        + Executable._executable_traverse_internals 
    4597    ) 
    4598 
    4599    selects: List[SelectBase] 
    4600 
    4601    _is_from_container = True 
    4602    _auto_correlate = False 
    4603 
    4604    def __init__( 
    4605        self, 
    4606        keyword: _CompoundSelectKeyword, 
    4607        *selects: _SelectStatementForCompoundArgument[Unpack[_Ts]], 
    4608    ): 
    4609        self.keyword = keyword 
    4610        self.selects = [ 
    4611            coercions.expect( 
    4612                roles.CompoundElementRole, s, apply_propagate_attrs=self 
    4613            ).self_group(against=self) 
    4614            for s in selects 
    4615        ] 
    4616 
    4617        GenerativeSelect.__init__(self) 
    4618 
    4619    @classmethod 
    4620    def _create_union( 
    4621        cls, *selects: _SelectStatementForCompoundArgument[Unpack[_Ts]] 
    4622    ) -> CompoundSelect[Unpack[_Ts]]: 
    4623        return CompoundSelect(_CompoundSelectKeyword.UNION, *selects) 
    4624 
    4625    @classmethod 
    4626    def _create_union_all( 
    4627        cls, *selects: _SelectStatementForCompoundArgument[Unpack[_Ts]] 
    4628    ) -> CompoundSelect[Unpack[_Ts]]: 
    4629        return CompoundSelect(_CompoundSelectKeyword.UNION_ALL, *selects) 
    4630 
    4631    @classmethod 
    4632    def _create_except( 
    4633        cls, *selects: _SelectStatementForCompoundArgument[Unpack[_Ts]] 
    4634    ) -> CompoundSelect[Unpack[_Ts]]: 
    4635        return CompoundSelect(_CompoundSelectKeyword.EXCEPT, *selects) 
    4636 
    4637    @classmethod 
    4638    def _create_except_all( 
    4639        cls, *selects: _SelectStatementForCompoundArgument[Unpack[_Ts]] 
    4640    ) -> CompoundSelect[Unpack[_Ts]]: 
    4641        return CompoundSelect(_CompoundSelectKeyword.EXCEPT_ALL, *selects) 
    4642 
    4643    @classmethod 
    4644    def _create_intersect( 
    4645        cls, *selects: _SelectStatementForCompoundArgument[Unpack[_Ts]] 
    4646    ) -> CompoundSelect[Unpack[_Ts]]: 
    4647        return CompoundSelect(_CompoundSelectKeyword.INTERSECT, *selects) 
    4648 
    4649    @classmethod 
    4650    def _create_intersect_all( 
    4651        cls, *selects: _SelectStatementForCompoundArgument[Unpack[_Ts]] 
    4652    ) -> CompoundSelect[Unpack[_Ts]]: 
    4653        return CompoundSelect(_CompoundSelectKeyword.INTERSECT_ALL, *selects) 
    4654 
    4655    def _scalar_type(self) -> TypeEngine[Any]: 
    4656        return self.selects[0]._scalar_type() 
    4657 
    4658    def self_group( 
    4659        self, against: Optional[OperatorType] = None 
    4660    ) -> GroupedElement: 
    4661        return SelectStatementGrouping(self) 
    4662 
    4663    def is_derived_from(self, fromclause: Optional[FromClause]) -> bool: 
    4664        for s in self.selects: 
    4665            if s.is_derived_from(fromclause): 
    4666                return True 
    4667        return False 
    4668 
    4669    def set_label_style(self, style: SelectLabelStyle) -> Self: 
    4670        if self._label_style is not style: 
    4671            self = self._generate() 
    4672            select_0 = self.selects[0].set_label_style(style) 
    4673            self.selects = [select_0] + self.selects[1:] 
    4674 
    4675        return self 
    4676 
    4677    def _ensure_disambiguated_names(self) -> Self: 
    4678        new_select = self.selects[0]._ensure_disambiguated_names() 
    4679        if new_select is not self.selects[0]: 
    4680            self = self._generate() 
    4681            self.selects = [new_select] + self.selects[1:] 
    4682 
    4683        return self 
    4684 
    4685    def _generate_fromclause_column_proxies( 
    4686        self, 
    4687        subquery: FromClause, 
    4688        columns: ColumnCollection[str, KeyedColumnElement[Any]], 
    4689        primary_key: ColumnSet, 
    4690        foreign_keys: Set[KeyedColumnElement[Any]], 
    4691        *, 
    4692        proxy_compound_columns: Optional[ 
    4693            Iterable[Sequence[ColumnElement[Any]]] 
    4694        ] = None, 
    4695    ) -> None: 
    4696        # this is a slightly hacky thing - the union exports a 
    4697        # column that resembles just that of the *first* selectable. 
    4698        # to get at a "composite" column, particularly foreign keys, 
    4699        # you have to dig through the proxies collection which we 
    4700        # generate below. 
    4701        select_0 = self.selects[0] 
    4702 
    4703        if self._label_style is not LABEL_STYLE_DEFAULT: 
    4704            select_0 = select_0.set_label_style(self._label_style) 
    4705 
    4706        # hand-construct the "_proxies" collection to include all 
    4707        # derived columns place a 'weight' annotation corresponding 
    4708        # to how low in the list of select()s the column occurs, so 
    4709        # that the corresponding_column() operation can resolve 
    4710        # conflicts 
    4711        extra_col_iterator = zip( 
    4712            *[ 
    4713                [ 
    4714                    c._annotate(dd) 
    4715                    for c in stmt._all_selected_columns 
    4716                    if is_column_element(c) 
    4717                ] 
    4718                for dd, stmt in [ 
    4719                    ({"weight": i + 1}, stmt) 
    4720                    for i, stmt in enumerate(self.selects) 
    4721                ] 
    4722            ] 
    4723        ) 
    4724 
    4725        # the incoming proxy_compound_columns can be present also if this is 
    4726        # a compound embedded in a compound.  it's probably more appropriate 
    4727        # that we generate new weights local to this nested compound, though 
    4728        # i haven't tried to think what it means for compound nested in 
    4729        # compound 
    4730        select_0._generate_fromclause_column_proxies( 
    4731            subquery, 
    4732            columns, 
    4733            proxy_compound_columns=extra_col_iterator, 
    4734            primary_key=primary_key, 
    4735            foreign_keys=foreign_keys, 
    4736        ) 
    4737 
    4738    def _refresh_for_new_column(self, column: ColumnElement[Any]) -> None: 
    4739        super()._refresh_for_new_column(column) 
    4740        for select in self.selects: 
    4741            select._refresh_for_new_column(column) 
    4742 
    4743    @util.ro_non_memoized_property 
    4744    def _all_selected_columns(self) -> _SelectIterable: 
    4745        return self.selects[0]._all_selected_columns 
    4746 
    4747    @util.ro_non_memoized_property 
    4748    def selected_columns( 
    4749        self, 
    4750    ) -> ColumnCollection[str, ColumnElement[Any]]: 
    4751        """A :class:`_expression.ColumnCollection` 
    4752        representing the columns that 
    4753        this SELECT statement or similar construct returns in its result set, 
    4754        not including :class:`_sql.TextClause` constructs. 
    4755 
    4756        For a :class:`_expression.CompoundSelect`, the 
    4757        :attr:`_expression.CompoundSelect.selected_columns` 
    4758        attribute returns the selected 
    4759        columns of the first SELECT statement contained within the series of 
    4760        statements within the set operation. 
    4761 
    4762        .. seealso:: 
    4763 
    4764            :attr:`_sql.Select.selected_columns` 
    4765 
    4766        .. versionadded:: 1.4 
    4767 
    4768        """ 
    4769        return self.selects[0].selected_columns 
    4770 
    4771 
    4772# backwards compat 
    4773for elem in _CompoundSelectKeyword: 
    4774    setattr(CompoundSelect, elem.name, elem) 
    4775 
    4776 
    4777@CompileState.plugin_for("default", "select") 
    4778class SelectState(util.MemoizedSlots, CompileState): 
    4779    __slots__ = ( 
    4780        "from_clauses", 
    4781        "froms", 
    4782        "columns_plus_names", 
    4783        "_label_resolve_dict", 
    4784    ) 
    4785 
    4786    if TYPE_CHECKING: 
    4787        default_select_compile_options: CacheableOptions 
    4788    else: 
    4789 
    4790        class default_select_compile_options(CacheableOptions): 
    4791            _cache_key_traversal = [] 
    4792 
    4793    if TYPE_CHECKING: 
    4794 
    4795        @classmethod 
    4796        def get_plugin_class( 
    4797            cls, statement: Executable 
    4798        ) -> Type[SelectState]: ... 
    4799 
    4800    def __init__( 
    4801        self, 
    4802        statement: Select[Unpack[TupleAny]], 
    4803        compiler: SQLCompiler, 
    4804        **kw: Any, 
    4805    ): 
    4806        self.statement = statement 
    4807        self.from_clauses = statement._from_obj 
    4808 
    4809        for memoized_entities in statement._memoized_select_entities: 
    4810            self._setup_joins( 
    4811                memoized_entities._setup_joins, memoized_entities._raw_columns 
    4812            ) 
    4813 
    4814        if statement._setup_joins: 
    4815            self._setup_joins(statement._setup_joins, statement._raw_columns) 
    4816 
    4817        self.froms = self._get_froms(statement) 
    4818 
    4819        self.columns_plus_names = statement._generate_columns_plus_names(True) 
    4820 
    4821    @classmethod 
    4822    def _plugin_not_implemented(cls) -> NoReturn: 
    4823        raise NotImplementedError( 
    4824            "The default SELECT construct without plugins does not " 
    4825            "implement this method." 
    4826        ) 
    4827 
    4828    @classmethod 
    4829    def get_column_descriptions( 
    4830        cls, statement: Select[Unpack[TupleAny]] 
    4831    ) -> List[Dict[str, Any]]: 
    4832        return [ 
    4833            { 
    4834                "name": name, 
    4835                "type": element.type, 
    4836                "expr": element, 
    4837            } 
    4838            for _, name, _, element, _ in ( 
    4839                statement._generate_columns_plus_names(False) 
    4840            ) 
    4841        ] 
    4842 
    4843    @classmethod 
    4844    def from_statement( 
    4845        cls, 
    4846        statement: Select[Unpack[TupleAny]], 
    4847        from_statement: roles.ReturnsRowsRole, 
    4848    ) -> ExecutableReturnsRows: 
    4849        cls._plugin_not_implemented() 
    4850 
    4851    @classmethod 
    4852    def get_columns_clause_froms( 
    4853        cls, statement: Select[Unpack[TupleAny]] 
    4854    ) -> List[FromClause]: 
    4855        return cls._normalize_froms( 
    4856            itertools.chain.from_iterable( 
    4857                element._from_objects for element in statement._raw_columns 
    4858            ) 
    4859        ) 
    4860 
    4861    @classmethod 
    4862    def _column_naming_convention( 
    4863        cls, label_style: SelectLabelStyle 
    4864    ) -> _LabelConventionCallable: 
    4865        table_qualified = label_style is LABEL_STYLE_TABLENAME_PLUS_COL 
    4866 
    4867        dedupe = label_style is not LABEL_STYLE_NONE 
    4868 
    4869        pa = prefix_anon_map() 
    4870        names = set() 
    4871 
    4872        def go( 
    4873            c: Union[ColumnElement[Any], TextClause], 
    4874            col_name: Optional[str] = None, 
    4875        ) -> Optional[str]: 
    4876            if is_text_clause(c): 
    4877                return None 
    4878            elif TYPE_CHECKING: 
    4879                assert is_column_element(c) 
    4880 
    4881            if not dedupe: 
    4882                name = c._proxy_key 
    4883                if name is None: 
    4884                    name = "_no_label" 
    4885                return name 
    4886 
    4887            name = c._tq_key_label if table_qualified else c._proxy_key 
    4888 
    4889            if name is None: 
    4890                name = "_no_label" 
    4891                if name in names: 
    4892                    return c._anon_label(name) % pa 
    4893                else: 
    4894                    names.add(name) 
    4895                    return name 
    4896 
    4897            elif name in names: 
    4898                return ( 
    4899                    c._anon_tq_key_label % pa 
    4900                    if table_qualified 
    4901                    else c._anon_key_label % pa 
    4902                ) 
    4903            else: 
    4904                names.add(name) 
    4905                return name 
    4906 
    4907        return go 
    4908 
    4909    def _get_froms( 
    4910        self, statement: Select[Unpack[TupleAny]] 
    4911    ) -> List[FromClause]: 
    4912        ambiguous_table_name_map: _AmbiguousTableNameMap 
    4913        self._ambiguous_table_name_map = ambiguous_table_name_map = {} 
    4914 
    4915        return self._normalize_froms( 
    4916            itertools.chain( 
    4917                self.from_clauses, 
    4918                itertools.chain.from_iterable( 
    4919                    [ 
    4920                        element._from_objects 
    4921                        for element in statement._raw_columns 
    4922                    ] 
    4923                ), 
    4924                itertools.chain.from_iterable( 
    4925                    [ 
    4926                        element._from_objects 
    4927                        for element in statement._where_criteria 
    4928                    ] 
    4929                ), 
    4930            ), 
    4931            check_statement=statement, 
    4932            ambiguous_table_name_map=ambiguous_table_name_map, 
    4933        ) 
    4934 
    4935    @classmethod 
    4936    def _normalize_froms( 
    4937        cls, 
    4938        iterable_of_froms: Iterable[FromClause], 
    4939        check_statement: Optional[Select[Unpack[TupleAny]]] = None, 
    4940        ambiguous_table_name_map: Optional[_AmbiguousTableNameMap] = None, 
    4941    ) -> List[FromClause]: 
    4942        """given an iterable of things to select FROM, reduce them to what 
    4943        would actually render in the FROM clause of a SELECT. 
    4944 
    4945        This does the job of checking for JOINs, tables, etc. that are in fact 
    4946        overlapping due to cloning, adaption, present in overlapping joins, 
    4947        etc. 
    4948 
    4949        """ 
    4950        seen: Set[FromClause] = set() 
    4951        froms: List[FromClause] = [] 
    4952 
    4953        for item in iterable_of_froms: 
    4954            if is_subquery(item) and item.element is check_statement: 
    4955                raise exc.InvalidRequestError( 
    4956                    "select() construct refers to itself as a FROM" 
    4957                ) 
    4958 
    4959            if not seen.intersection(item._cloned_set): 
    4960                froms.append(item) 
    4961                seen.update(item._cloned_set) 
    4962 
    4963        if froms: 
    4964            toremove = set( 
    4965                itertools.chain.from_iterable( 
    4966                    [_expand_cloned(f._hide_froms) for f in froms] 
    4967                ) 
    4968            ) 
    4969            if toremove: 
    4970                # filter out to FROM clauses not in the list, 
    4971                # using a list to maintain ordering 
    4972                froms = [f for f in froms if f not in toremove] 
    4973 
    4974            if ambiguous_table_name_map is not None: 
    4975                ambiguous_table_name_map.update( 
    4976                    ( 
    4977                        fr.name, 
    4978                        _anonymous_label.safe_construct( 
    4979                            hash(fr.name), fr.name 
    4980                        ), 
    4981                    ) 
    4982                    for item in froms 
    4983                    for fr in item._from_objects 
    4984                    if is_table(fr) 
    4985                    and fr.schema 
    4986                    and fr.name not in ambiguous_table_name_map 
    4987                ) 
    4988 
    4989        return froms 
    4990 
    4991    def _get_display_froms( 
    4992        self, 
    4993        explicit_correlate_froms: Optional[Sequence[FromClause]] = None, 
    4994        implicit_correlate_froms: Optional[Sequence[FromClause]] = None, 
    4995    ) -> List[FromClause]: 
    4996        """Return the full list of 'from' clauses to be displayed. 
    4997 
    4998        Takes into account a set of existing froms which may be 
    4999        rendered in the FROM clause of enclosing selects; this Select 
    5000        may want to leave those absent if it is automatically 
    5001        correlating. 
    5002 
    5003        """ 
    5004 
    5005        froms = self.froms 
    5006 
    5007        if self.statement._correlate: 
    5008            to_correlate = self.statement._correlate 
    5009            if to_correlate: 
    5010                froms = [ 
    5011                    f 
    5012                    for f in froms 
    5013                    if f 
    5014                    not in _cloned_intersection( 
    5015                        _cloned_intersection( 
    5016                            froms, explicit_correlate_froms or () 
    5017                        ), 
    5018                        to_correlate, 
    5019                    ) 
    5020                ] 
    5021 
    5022        if self.statement._correlate_except is not None: 
    5023            froms = [ 
    5024                f 
    5025                for f in froms 
    5026                if f 
    5027                not in _cloned_difference( 
    5028                    _cloned_intersection( 
    5029                        froms, explicit_correlate_froms or () 
    5030                    ), 
    5031                    self.statement._correlate_except, 
    5032                ) 
    5033            ] 
    5034 
    5035        if ( 
    5036            self.statement._auto_correlate 
    5037            and implicit_correlate_froms 
    5038            and len(froms) > 1 
    5039        ): 
    5040            froms = [ 
    5041                f 
    5042                for f in froms 
    5043                if f 
    5044                not in _cloned_intersection(froms, implicit_correlate_froms) 
    5045            ] 
    5046 
    5047            if not len(froms): 
    5048                raise exc.InvalidRequestError( 
    5049                    "Select statement '%r" 
    5050                    "' returned no FROM clauses " 
    5051                    "due to auto-correlation; " 
    5052                    "specify correlate(<tables>) " 
    5053                    "to control correlation " 
    5054                    "manually." % self.statement 
    5055                ) 
    5056 
    5057        return froms 
    5058 
    5059    def _memoized_attr__label_resolve_dict( 
    5060        self, 
    5061    ) -> Tuple[ 
    5062        Dict[str, ColumnElement[Any]], 
    5063        Dict[str, ColumnElement[Any]], 
    5064        Dict[str, ColumnElement[Any]], 
    5065    ]: 
    5066        with_cols: Dict[str, ColumnElement[Any]] = { 
    5067            c._tq_label or c.key: c 
    5068            for c in self.statement._all_selected_columns 
    5069            if c._allow_label_resolve 
    5070        } 
    5071        only_froms: Dict[str, ColumnElement[Any]] = { 
    5072            c.key: c  # type: ignore 
    5073            for c in _select_iterables(self.froms) 
    5074            if c._allow_label_resolve 
    5075        } 
    5076        only_cols: Dict[str, ColumnElement[Any]] = with_cols.copy() 
    5077        for key, value in only_froms.items(): 
    5078            with_cols.setdefault(key, value) 
    5079 
    5080        return with_cols, only_froms, only_cols 
    5081 
    5082    @classmethod 
    5083    def determine_last_joined_entity( 
    5084        cls, stmt: Select[Unpack[TupleAny]] 
    5085    ) -> Optional[_JoinTargetElement]: 
    5086        if stmt._setup_joins: 
    5087            return stmt._setup_joins[-1][0] 
    5088        else: 
    5089            return None 
    5090 
    5091    @classmethod 
    5092    def all_selected_columns( 
    5093        cls, statement: Select[Unpack[TupleAny]] 
    5094    ) -> _SelectIterable: 
    5095        return [c for c in _select_iterables(statement._raw_columns)] 
    5096 
    5097    def _setup_joins( 
    5098        self, 
    5099        args: Tuple[_SetupJoinsElement, ...], 
    5100        raw_columns: List[_ColumnsClauseElement], 
    5101    ) -> None: 
    5102        for right, onclause, left, flags in args: 
    5103            if TYPE_CHECKING: 
    5104                if onclause is not None: 
    5105                    assert isinstance(onclause, ColumnElement) 
    5106 
    5107            explicit_left = left 
    5108            isouter = flags["isouter"] 
    5109            full = flags["full"] 
    5110 
    5111            if left is None: 
    5112                ( 
    5113                    left, 
    5114                    replace_from_obj_index, 
    5115                ) = self._join_determine_implicit_left_side( 
    5116                    raw_columns, left, right, onclause 
    5117                ) 
    5118            else: 
    5119                (replace_from_obj_index) = self._join_place_explicit_left_side( 
    5120                    left 
    5121                ) 
    5122 
    5123            # these assertions can be made here, as if the right/onclause 
    5124            # contained ORM elements, the select() statement would have been 
    5125            # upgraded to an ORM select, and this method would not be called; 
    5126            # orm.context.ORMSelectCompileState._join() would be 
    5127            # used instead. 
    5128            if TYPE_CHECKING: 
    5129                assert isinstance(right, FromClause) 
    5130                if onclause is not None: 
    5131                    assert isinstance(onclause, ColumnElement) 
    5132 
    5133            if replace_from_obj_index is not None: 
    5134                # splice into an existing element in the 
    5135                # self._from_obj list 
    5136                left_clause = self.from_clauses[replace_from_obj_index] 
    5137 
    5138                if explicit_left is not None and onclause is None: 
    5139                    onclause = Join._join_condition(explicit_left, right) 
    5140 
    5141                self.from_clauses = ( 
    5142                    self.from_clauses[:replace_from_obj_index] 
    5143                    + ( 
    5144                        Join( 
    5145                            left_clause, 
    5146                            right, 
    5147                            onclause, 
    5148                            isouter=isouter, 
    5149                            full=full, 
    5150                        ), 
    5151                    ) 
    5152                    + self.from_clauses[replace_from_obj_index + 1 :] 
    5153                ) 
    5154            else: 
    5155                assert left is not None 
    5156                self.from_clauses = self.from_clauses + ( 
    5157                    Join(left, right, onclause, isouter=isouter, full=full), 
    5158                ) 
    5159 
    5160    @util.preload_module("sqlalchemy.sql.util") 
    5161    def _join_determine_implicit_left_side( 
    5162        self, 
    5163        raw_columns: List[_ColumnsClauseElement], 
    5164        left: Optional[FromClause], 
    5165        right: _JoinTargetElement, 
    5166        onclause: Optional[ColumnElement[Any]], 
    5167    ) -> Tuple[Optional[FromClause], Optional[int]]: 
    5168        """When join conditions don't express the left side explicitly, 
    5169        determine if an existing FROM or entity in this query 
    5170        can serve as the left hand side. 
    5171 
    5172        """ 
    5173 
    5174        sql_util = util.preloaded.sql_util 
    5175 
    5176        replace_from_obj_index: Optional[int] = None 
    5177 
    5178        from_clauses = self.from_clauses 
    5179 
    5180        if from_clauses: 
    5181            indexes: List[int] = sql_util.find_left_clause_to_join_from( 
    5182                from_clauses, right, onclause 
    5183            ) 
    5184 
    5185            if len(indexes) == 1: 
    5186                replace_from_obj_index = indexes[0] 
    5187                left = from_clauses[replace_from_obj_index] 
    5188        else: 
    5189            potential = {} 
    5190            statement = self.statement 
    5191 
    5192            for from_clause in itertools.chain( 
    5193                itertools.chain.from_iterable( 
    5194                    [element._from_objects for element in raw_columns] 
    5195                ), 
    5196                itertools.chain.from_iterable( 
    5197                    [ 
    5198                        element._from_objects 
    5199                        for element in statement._where_criteria 
    5200                    ] 
    5201                ), 
    5202            ): 
    5203                potential[from_clause] = () 
    5204 
    5205            all_clauses = list(potential.keys()) 
    5206            indexes = sql_util.find_left_clause_to_join_from( 
    5207                all_clauses, right, onclause 
    5208            ) 
    5209 
    5210            if len(indexes) == 1: 
    5211                left = all_clauses[indexes[0]] 
    5212 
    5213        if len(indexes) > 1: 
    5214            raise exc.InvalidRequestError( 
    5215                "Can't determine which FROM clause to join " 
    5216                "from, there are multiple FROMS which can " 
    5217                "join to this entity. Please use the .select_from() " 
    5218                "method to establish an explicit left side, as well as " 
    5219                "providing an explicit ON clause if not present already to " 
    5220                "help resolve the ambiguity." 
    5221            ) 
    5222        elif not indexes: 
    5223            raise exc.InvalidRequestError( 
    5224                "Don't know how to join to %r. " 
    5225                "Please use the .select_from() " 
    5226                "method to establish an explicit left side, as well as " 
    5227                "providing an explicit ON clause if not present already to " 
    5228                "help resolve the ambiguity." % (right,) 
    5229            ) 
    5230        return left, replace_from_obj_index 
    5231 
    5232    @util.preload_module("sqlalchemy.sql.util") 
    5233    def _join_place_explicit_left_side( 
    5234        self, left: FromClause 
    5235    ) -> Optional[int]: 
    5236        replace_from_obj_index: Optional[int] = None 
    5237 
    5238        sql_util = util.preloaded.sql_util 
    5239 
    5240        from_clauses = list(self.statement._iterate_from_elements()) 
    5241 
    5242        if from_clauses: 
    5243            indexes: List[int] = sql_util.find_left_clause_that_matches_given( 
    5244                self.from_clauses, left 
    5245            ) 
    5246        else: 
    5247            indexes = [] 
    5248 
    5249        if len(indexes) > 1: 
    5250            raise exc.InvalidRequestError( 
    5251                "Can't identify which entity in which to assign the " 
    5252                "left side of this join.   Please use a more specific " 
    5253                "ON clause." 
    5254            ) 
    5255 
    5256        # have an index, means the left side is already present in 
    5257        # an existing FROM in the self._from_obj tuple 
    5258        if indexes: 
    5259            replace_from_obj_index = indexes[0] 
    5260 
    5261        # no index, means we need to add a new element to the 
    5262        # self._from_obj tuple 
    5263 
    5264        return replace_from_obj_index 
    5265 
    5266 
    5267class _SelectFromElements: 
    5268    __slots__ = () 
    5269 
    5270    _raw_columns: List[_ColumnsClauseElement] 
    5271    _where_criteria: Tuple[ColumnElement[Any], ...] 
    5272    _from_obj: Tuple[FromClause, ...] 
    5273 
    5274    def _iterate_from_elements(self) -> Iterator[FromClause]: 
    5275        # note this does not include elements 
    5276        # in _setup_joins 
    5277 
    5278        seen = set() 
    5279        for element in self._raw_columns: 
    5280            for fr in element._from_objects: 
    5281                if fr in seen: 
    5282                    continue 
    5283                seen.add(fr) 
    5284                yield fr 
    5285        for element in self._where_criteria: 
    5286            for fr in element._from_objects: 
    5287                if fr in seen: 
    5288                    continue 
    5289                seen.add(fr) 
    5290                yield fr 
    5291        for element in self._from_obj: 
    5292            if element in seen: 
    5293                continue 
    5294            seen.add(element) 
    5295            yield element 
    5296 
    5297 
    5298class _MemoizedSelectEntities( 
    5299    cache_key.HasCacheKey, traversals.HasCopyInternals, visitors.Traversible 
    5300): 
    5301    """represents partial state from a Select object, for the case 
    5302    where Select.columns() has redefined the set of columns/entities the 
    5303    statement will be SELECTing from.  This object represents 
    5304    the entities from the SELECT before that transformation was applied, 
    5305    so that transformations that were made in terms of the SELECT at that 
    5306    time, such as join() as well as options(), can access the correct context. 
    5307 
    5308    In previous SQLAlchemy versions, this wasn't needed because these 
    5309    constructs calculated everything up front, like when you called join() 
    5310    or options(), it did everything to figure out how that would translate 
    5311    into specific SQL constructs that would be ready to send directly to the 
    5312    SQL compiler when needed.  But as of 
    5313    1.4, all of that stuff is done in the compilation phase, during the 
    5314    "compile state" portion of the process, so that the work can all be 
    5315    cached.  So it needs to be able to resolve joins/options2 based on what 
    5316    the list of entities was when those methods were called. 
    5317 
    5318 
    5319    """ 
    5320 
    5321    __visit_name__ = "memoized_select_entities" 
    5322 
    5323    _traverse_internals: _TraverseInternalsType = [ 
    5324        ("_raw_columns", InternalTraversal.dp_clauseelement_list), 
    5325        ("_setup_joins", InternalTraversal.dp_setup_join_tuple), 
    5326        ("_with_options", InternalTraversal.dp_executable_options), 
    5327    ] 
    5328 
    5329    _is_clone_of: Optional[ClauseElement] 
    5330    _raw_columns: List[_ColumnsClauseElement] 
    5331    _setup_joins: Tuple[_SetupJoinsElement, ...] 
    5332    _with_options: Tuple[ExecutableOption, ...] 
    5333 
    5334    _annotations = util.EMPTY_DICT 
    5335 
    5336    def _clone(self, **kw: Any) -> Self: 
    5337        c = self.__class__.__new__(self.__class__) 
    5338        c.__dict__ = {k: v for k, v in self.__dict__.items()} 
    5339 
    5340        c._is_clone_of = self.__dict__.get("_is_clone_of", self) 
    5341        return c 
    5342 
    5343    @classmethod 
    5344    def _generate_for_statement( 
    5345        cls, select_stmt: Select[Unpack[TupleAny]] 
    5346    ) -> None: 
    5347        if select_stmt._setup_joins or select_stmt._with_options: 
    5348            self = _MemoizedSelectEntities() 
    5349            self._raw_columns = select_stmt._raw_columns 
    5350            self._setup_joins = select_stmt._setup_joins 
    5351            self._with_options = select_stmt._with_options 
    5352 
    5353            select_stmt._memoized_select_entities += (self,) 
    5354            select_stmt._raw_columns = [] 
    5355            select_stmt._setup_joins = select_stmt._with_options = () 
    5356 
    5357 
    5358class Select( 
    5359    HasPrefixes, 
    5360    HasSuffixes, 
    5361    HasHints, 
    5362    HasCompileState, 
    5363    HasSyntaxExtensions[ 
    5364        Literal["post_select", "pre_columns", "post_criteria", "post_body"] 
    5365    ], 
    5366    _SelectFromElements, 
    5367    GenerativeSelect, 
    5368    TypedReturnsRows[Unpack[_Ts]], 
    5369): 
    5370    """Represents a ``SELECT`` statement. 
    5371 
    5372    The :class:`_sql.Select` object is normally constructed using the 
    5373    :func:`_sql.select` function.  See that function for details. 
    5374 
    5375    Available extension points: 
    5376 
    5377    * ``post_select``: applies additional logic after the ``SELECT`` keyword. 
    5378    * ``pre_columns``: applies additional logic between the ``DISTINCT`` 
    5379        keyword (if any) and the list of columns. 
    5380    * ``post_criteria``: applies additional logic after the ``HAVING`` clause. 
    5381    * ``post_body``: applies additional logic after the ``FOR UPDATE`` clause. 
    5382 
    5383    .. seealso:: 
    5384 
    5385        :func:`_sql.select` 
    5386 
    5387        :ref:`tutorial_selecting_data` - in the 2.0 tutorial 
    5388 
    5389    """ 
    5390 
    5391    __visit_name__ = "select" 
    5392 
    5393    _setup_joins: Tuple[_SetupJoinsElement, ...] = () 
    5394    _memoized_select_entities: Tuple[TODO_Any, ...] = () 
    5395 
    5396    _raw_columns: List[_ColumnsClauseElement] 
    5397 
    5398    _distinct: bool = False 
    5399    _distinct_on: Tuple[ColumnElement[Any], ...] = () 
    5400    _correlate: Tuple[FromClause, ...] = () 
    5401    _correlate_except: Optional[Tuple[FromClause, ...]] = None 
    5402    _where_criteria: Tuple[ColumnElement[Any], ...] = () 
    5403    _having_criteria: Tuple[ColumnElement[Any], ...] = () 
    5404    _from_obj: Tuple[FromClause, ...] = () 
    5405 
    5406    _position_map = util.immutabledict( 
    5407        { 
    5408            "post_select": "_post_select_clause", 
    5409            "pre_columns": "_pre_columns_clause", 
    5410            "post_criteria": "_post_criteria_clause", 
    5411            "post_body": "_post_body_clause", 
    5412        } 
    5413    ) 
    5414 
    5415    _post_select_clause: Optional[ClauseElement] = None 
    5416    """extension point for a ClauseElement that will be compiled directly 
    5417    after the SELECT keyword. 
    5418 
    5419    .. versionadded:: 2.1 
    5420 
    5421    """ 
    5422 
    5423    _pre_columns_clause: Optional[ClauseElement] = None 
    5424    """extension point for a ClauseElement that will be compiled directly 
    5425    before the "columns" clause; after DISTINCT (if present). 
    5426 
    5427    .. versionadded:: 2.1 
    5428 
    5429    """ 
    5430 
    5431    _post_criteria_clause: Optional[ClauseElement] = None 
    5432    """extension point for a ClauseElement that will be compiled directly 
    5433    after "criteria", following the HAVING clause but before ORDER BY. 
    5434 
    5435    .. versionadded:: 2.1 
    5436 
    5437    """ 
    5438 
    5439    _post_body_clause: Optional[ClauseElement] = None 
    5440    """extension point for a ClauseElement that will be compiled directly 
    5441    after the "body", following the ORDER BY, LIMIT, and FOR UPDATE sections 
    5442    of the SELECT. 
    5443 
    5444    .. versionadded:: 2.1 
    5445 
    5446    """ 
    5447 
    5448    _auto_correlate = True 
    5449    _is_select_statement = True 
    5450    _compile_options: CacheableOptions = ( 
    5451        SelectState.default_select_compile_options 
    5452    ) 
    5453 
    5454    _traverse_internals: _TraverseInternalsType = ( 
    5455        [ 
    5456            ("_raw_columns", InternalTraversal.dp_clauseelement_list), 
    5457            ( 
    5458                "_memoized_select_entities", 
    5459                InternalTraversal.dp_memoized_select_entities, 
    5460            ), 
    5461            ("_from_obj", InternalTraversal.dp_clauseelement_list), 
    5462            ("_where_criteria", InternalTraversal.dp_clauseelement_tuple), 
    5463            ("_having_criteria", InternalTraversal.dp_clauseelement_tuple), 
    5464            ("_order_by_clauses", InternalTraversal.dp_clauseelement_tuple), 
    5465            ("_group_by_clauses", InternalTraversal.dp_clauseelement_tuple), 
    5466            ("_setup_joins", InternalTraversal.dp_setup_join_tuple), 
    5467            ("_correlate", InternalTraversal.dp_clauseelement_tuple), 
    5468            ("_correlate_except", InternalTraversal.dp_clauseelement_tuple), 
    5469            ("_limit_clause", InternalTraversal.dp_clauseelement), 
    5470            ("_offset_clause", InternalTraversal.dp_clauseelement), 
    5471            ("_fetch_clause", InternalTraversal.dp_clauseelement), 
    5472            ("_fetch_clause_options", InternalTraversal.dp_plain_dict), 
    5473            ("_for_update_arg", InternalTraversal.dp_clauseelement), 
    5474            ("_distinct", InternalTraversal.dp_boolean), 
    5475            ("_distinct_on", InternalTraversal.dp_clauseelement_tuple), 
    5476            ("_label_style", InternalTraversal.dp_plain_obj), 
    5477            ("_post_select_clause", InternalTraversal.dp_clauseelement), 
    5478            ("_pre_columns_clause", InternalTraversal.dp_clauseelement), 
    5479            ("_post_criteria_clause", InternalTraversal.dp_clauseelement), 
    5480            ("_post_body_clause", InternalTraversal.dp_clauseelement), 
    5481        ] 
    5482        + HasCTE._has_ctes_traverse_internals 
    5483        + HasPrefixes._has_prefixes_traverse_internals 
    5484        + HasSuffixes._has_suffixes_traverse_internals 
    5485        + HasHints._has_hints_traverse_internals 
    5486        + SupportsCloneAnnotations._clone_annotations_traverse_internals 
    5487        + Executable._executable_traverse_internals 
    5488        + DialectKWArgs._dialect_kwargs_traverse_internals 
    5489    ) 
    5490 
    5491    _cache_key_traversal: _CacheKeyTraversalType = _traverse_internals + [ 
    5492        ("_compile_options", InternalTraversal.dp_has_cache_key) 
    5493    ] 
    5494 
    5495    _compile_state_factory: Type[SelectState] 
    5496 
    5497    @classmethod 
    5498    def _create_raw_select(cls, **kw: Any) -> Select[Unpack[TupleAny]]: 
    5499        """Create a :class:`.Select` using raw ``__new__`` with no coercions. 
    5500 
    5501        Used internally to build up :class:`.Select` constructs with 
    5502        pre-established state. 
    5503 
    5504        """ 
    5505 
    5506        stmt = Select.__new__(Select) 
    5507        stmt.__dict__.update(kw) 
    5508        return stmt 
    5509 
    5510    def __init__( 
    5511        self, *entities: _ColumnsClauseArgument[Any], **dialect_kw: Any 
    5512    ): 
    5513        r"""Construct a new :class:`_expression.Select`. 
    5514 
    5515        The public constructor for :class:`_expression.Select` is the 
    5516        :func:`_sql.select` function. 
    5517 
    5518        """ 
    5519        self._raw_columns = [ 
    5520            coercions.expect( 
    5521                roles.ColumnsClauseRole, ent, apply_propagate_attrs=self 
    5522            ) 
    5523            for ent in entities 
    5524        ] 
    5525        GenerativeSelect.__init__(self) 
    5526 
    5527    def _apply_syntax_extension_to_self( 
    5528        self, extension: SyntaxExtension 
    5529    ) -> None: 
    5530        extension.apply_to_select(self) 
    5531 
    5532    def _scalar_type(self) -> TypeEngine[Any]: 
    5533        if not self._raw_columns: 
    5534            return NULLTYPE 
    5535        elem = self._raw_columns[0] 
    5536        cols = list(elem._select_iterable) 
    5537        return cols[0].type 
    5538 
    5539    def filter(self, *criteria: _ColumnExpressionArgument[bool]) -> Self: 
    5540        """A synonym for the :meth:`_sql.Select.where` method.""" 
    5541 
    5542        return self.where(*criteria) 
    5543 
    5544    def _filter_by_zero( 
    5545        self, 
    5546    ) -> Union[ 
    5547        FromClause, _JoinTargetProtocol, ColumnElement[Any], TextClause 
    5548    ]: 
    5549        if self._setup_joins: 
    5550            meth = SelectState.get_plugin_class( 
    5551                self 
    5552            ).determine_last_joined_entity 
    5553            _last_joined_entity = meth(self) 
    5554            if _last_joined_entity is not None: 
    5555                return _last_joined_entity 
    5556 
    5557        if self._from_obj: 
    5558            return self._from_obj[0] 
    5559 
    5560        return self._raw_columns[0] 
    5561 
    5562    if TYPE_CHECKING: 
    5563 
    5564        @overload 
    5565        def scalar_subquery( 
    5566            self: Select[_MAYBE_ENTITY], 
    5567        ) -> ScalarSelect[Any]: ... 
    5568 
    5569        @overload 
    5570        def scalar_subquery( 
    5571            self: Select[_NOT_ENTITY], 
    5572        ) -> ScalarSelect[_NOT_ENTITY]: ... 
    5573 
    5574        @overload 
    5575        def scalar_subquery(self) -> ScalarSelect[Any]: ... 
    5576 
    5577        def scalar_subquery(self) -> ScalarSelect[Any]: ... 
    5578 
    5579    def filter_by(self, **kwargs: Any) -> Self: 
    5580        r"""apply the given filtering criterion as a WHERE clause 
    5581        to this select. 
    5582 
    5583        """ 
    5584        from_entity = self._filter_by_zero() 
    5585 
    5586        clauses = [ 
    5587            _entity_namespace_key(from_entity, key) == value 
    5588            for key, value in kwargs.items() 
    5589        ] 
    5590        return self.filter(*clauses) 
    5591 
    5592    @property 
    5593    def column_descriptions(self) -> Any: 
    5594        """Return a :term:`plugin-enabled` 'column descriptions' structure 
    5595        referring to the columns which are SELECTed by this statement. 
    5596 
    5597        This attribute is generally useful when using the ORM, as an 
    5598        extended structure which includes information about mapped 
    5599        entities is returned.  The section :ref:`queryguide_inspection` 
    5600        contains more background. 
    5601 
    5602        For a Core-only statement, the structure returned by this accessor 
    5603        is derived from the same objects that are returned by the 
    5604        :attr:`.Select.selected_columns` accessor, formatted as a list of 
    5605        dictionaries which contain the keys ``name``, ``type`` and ``expr``, 
    5606        which indicate the column expressions to be selected:: 
    5607 
    5608            >>> stmt = select(user_table) 
    5609            >>> stmt.column_descriptions 
    5610            [ 
    5611                { 
    5612                    'name': 'id', 
    5613                    'type': Integer(), 
    5614                    'expr': Column('id', Integer(), ...)}, 
    5615                { 
    5616                    'name': 'name', 
    5617                    'type': String(length=30), 
    5618                    'expr': Column('name', String(length=30), ...)} 
    5619            ] 
    5620 
    5621        .. versionchanged:: 1.4.33 The :attr:`.Select.column_descriptions` 
    5622           attribute returns a structure for a Core-only set of entities, 
    5623           not just ORM-only entities. 
    5624 
    5625        .. seealso:: 
    5626 
    5627            :attr:`.UpdateBase.entity_description` - entity information for 
    5628            an :func:`.insert`, :func:`.update`, or :func:`.delete` 
    5629 
    5630            :ref:`queryguide_inspection` - ORM background 
    5631 
    5632        """ 
    5633        meth = SelectState.get_plugin_class(self).get_column_descriptions 
    5634        return meth(self) 
    5635 
    5636    def from_statement( 
    5637        self, statement: roles.ReturnsRowsRole 
    5638    ) -> ExecutableReturnsRows: 
    5639        """Apply the columns which this :class:`.Select` would select 
    5640        onto another statement. 
    5641 
    5642        This operation is :term:`plugin-specific` and will raise a not 
    5643        supported exception if this :class:`_sql.Select` does not select from 
    5644        plugin-enabled entities. 
    5645 
    5646 
    5647        The statement is typically either a :func:`_expression.text` or 
    5648        :func:`_expression.select` construct, and should return the set of 
    5649        columns appropriate to the entities represented by this 
    5650        :class:`.Select`. 
    5651 
    5652        .. seealso:: 
    5653 
    5654            :ref:`orm_queryguide_selecting_text` - usage examples in the 
    5655            ORM Querying Guide 
    5656 
    5657        """ 
    5658        meth = SelectState.get_plugin_class(self).from_statement 
    5659        return meth(self, statement) 
    5660 
    5661    @_generative 
    5662    def join( 
    5663        self, 
    5664        target: _JoinTargetArgument, 
    5665        onclause: Optional[_OnClauseArgument] = None, 
    5666        *, 
    5667        isouter: bool = False, 
    5668        full: bool = False, 
    5669    ) -> Self: 
    5670        r"""Create a SQL JOIN against this :class:`_expression.Select` 
    5671        object's criterion 
    5672        and apply generatively, returning the newly resulting 
    5673        :class:`_expression.Select`. 
    5674 
    5675        E.g.:: 
    5676 
    5677            stmt = select(user_table).join( 
    5678                address_table, user_table.c.id == address_table.c.user_id 
    5679            ) 
    5680 
    5681        The above statement generates SQL similar to: 
    5682 
    5683        .. sourcecode:: sql 
    5684 
    5685            SELECT user.id, user.name 
    5686            FROM user 
    5687            JOIN address ON user.id = address.user_id 
    5688 
    5689        .. versionchanged:: 1.4 :meth:`_expression.Select.join` now creates 
    5690           a :class:`_sql.Join` object between a :class:`_sql.FromClause` 
    5691           source that is within the FROM clause of the existing SELECT, 
    5692           and a given target :class:`_sql.FromClause`, and then adds 
    5693           this :class:`_sql.Join` to the FROM clause of the newly generated 
    5694           SELECT statement.    This is completely reworked from the behavior 
    5695           in 1.3, which would instead create a subquery of the entire 
    5696           :class:`_expression.Select` and then join that subquery to the 
    5697           target. 
    5698 
    5699           This is a **backwards incompatible change** as the previous behavior 
    5700           was mostly useless, producing an unnamed subquery rejected by 
    5701           most databases in any case.   The new behavior is modeled after 
    5702           that of the very successful :meth:`_orm.Query.join` method in the 
    5703           ORM, in order to support the functionality of :class:`_orm.Query` 
    5704           being available by using a :class:`_sql.Select` object with an 
    5705           :class:`_orm.Session`. 
    5706 
    5707           See the notes for this change at :ref:`change_select_join`. 
    5708 
    5709 
    5710        :param target: target table to join towards 
    5711 
    5712        :param onclause: ON clause of the join.  If omitted, an ON clause 
    5713         is generated automatically based on the :class:`_schema.ForeignKey` 
    5714         linkages between the two tables, if one can be unambiguously 
    5715         determined, otherwise an error is raised. 
    5716 
    5717        :param isouter: if True, generate LEFT OUTER join.  Same as 
    5718         :meth:`_expression.Select.outerjoin`. 
    5719 
    5720        :param full: if True, generate FULL OUTER join. 
    5721 
    5722        .. seealso:: 
    5723 
    5724            :ref:`tutorial_select_join` - in the :doc:`/tutorial/index` 
    5725 
    5726            :ref:`orm_queryguide_joins` - in the :ref:`queryguide_toplevel` 
    5727 
    5728            :meth:`_expression.Select.join_from` 
    5729 
    5730            :meth:`_expression.Select.outerjoin` 
    5731 
    5732        """  # noqa: E501 
    5733        join_target = coercions.expect( 
    5734            roles.JoinTargetRole, target, apply_propagate_attrs=self 
    5735        ) 
    5736        if onclause is not None: 
    5737            onclause_element = coercions.expect(roles.OnClauseRole, onclause) 
    5738        else: 
    5739            onclause_element = None 
    5740 
    5741        self._setup_joins += ( 
    5742            ( 
    5743                join_target, 
    5744                onclause_element, 
    5745                None, 
    5746                {"isouter": isouter, "full": full}, 
    5747            ), 
    5748        ) 
    5749        return self 
    5750 
    5751    def outerjoin_from( 
    5752        self, 
    5753        from_: _FromClauseArgument, 
    5754        target: _JoinTargetArgument, 
    5755        onclause: Optional[_OnClauseArgument] = None, 
    5756        *, 
    5757        full: bool = False, 
    5758    ) -> Self: 
    5759        r"""Create a SQL LEFT OUTER JOIN against this 
    5760        :class:`_expression.Select` object's criterion and apply generatively, 
    5761        returning the newly resulting :class:`_expression.Select`. 
    5762 
    5763        Usage is the same as that of :meth:`_selectable.Select.join_from`. 
    5764 
    5765        """ 
    5766        return self.join_from( 
    5767            from_, target, onclause=onclause, isouter=True, full=full 
    5768        ) 
    5769 
    5770    @_generative 
    5771    def join_from( 
    5772        self, 
    5773        from_: _FromClauseArgument, 
    5774        target: _JoinTargetArgument, 
    5775        onclause: Optional[_OnClauseArgument] = None, 
    5776        *, 
    5777        isouter: bool = False, 
    5778        full: bool = False, 
    5779    ) -> Self: 
    5780        r"""Create a SQL JOIN against this :class:`_expression.Select` 
    5781        object's criterion 
    5782        and apply generatively, returning the newly resulting 
    5783        :class:`_expression.Select`. 
    5784 
    5785        E.g.:: 
    5786 
    5787            stmt = select(user_table, address_table).join_from( 
    5788                user_table, address_table, user_table.c.id == address_table.c.user_id 
    5789            ) 
    5790 
    5791        The above statement generates SQL similar to: 
    5792 
    5793        .. sourcecode:: sql 
    5794 
    5795            SELECT user.id, user.name, address.id, address.email, address.user_id 
    5796            FROM user JOIN address ON user.id = address.user_id 
    5797 
    5798        .. versionadded:: 1.4 
    5799 
    5800        :param from\_: the left side of the join, will be rendered in the 
    5801         FROM clause and is roughly equivalent to using the 
    5802         :meth:`.Select.select_from` method. 
    5803 
    5804        :param target: target table to join towards 
    5805 
    5806        :param onclause: ON clause of the join. 
    5807 
    5808        :param isouter: if True, generate LEFT OUTER join.  Same as 
    5809         :meth:`_expression.Select.outerjoin`. 
    5810 
    5811        :param full: if True, generate FULL OUTER join. 
    5812 
    5813        .. seealso:: 
    5814 
    5815            :ref:`tutorial_select_join` - in the :doc:`/tutorial/index` 
    5816 
    5817            :ref:`orm_queryguide_joins` - in the :ref:`queryguide_toplevel` 
    5818 
    5819            :meth:`_expression.Select.join` 
    5820 
    5821        """  # noqa: E501 
    5822 
    5823        # note the order of parsing from vs. target is important here, as we 
    5824        # are also deriving the source of the plugin (i.e. the subject mapper 
    5825        # in an ORM query) which should favor the "from_" over the "target" 
    5826 
    5827        from_ = coercions.expect( 
    5828            roles.FromClauseRole, from_, apply_propagate_attrs=self 
    5829        ) 
    5830        join_target = coercions.expect( 
    5831            roles.JoinTargetRole, target, apply_propagate_attrs=self 
    5832        ) 
    5833        if onclause is not None: 
    5834            onclause_element = coercions.expect(roles.OnClauseRole, onclause) 
    5835        else: 
    5836            onclause_element = None 
    5837 
    5838        self._setup_joins += ( 
    5839            ( 
    5840                join_target, 
    5841                onclause_element, 
    5842                from_, 
    5843                {"isouter": isouter, "full": full}, 
    5844            ), 
    5845        ) 
    5846        return self 
    5847 
    5848    def outerjoin( 
    5849        self, 
    5850        target: _JoinTargetArgument, 
    5851        onclause: Optional[_OnClauseArgument] = None, 
    5852        *, 
    5853        full: bool = False, 
    5854    ) -> Self: 
    5855        """Create a left outer join. 
    5856 
    5857        Parameters are the same as that of :meth:`_expression.Select.join`. 
    5858 
    5859        .. versionchanged:: 1.4 :meth:`_expression.Select.outerjoin` now 
    5860           creates a :class:`_sql.Join` object between a 
    5861           :class:`_sql.FromClause` source that is within the FROM clause of 
    5862           the existing SELECT, and a given target :class:`_sql.FromClause`, 
    5863           and then adds this :class:`_sql.Join` to the FROM clause of the 
    5864           newly generated SELECT statement.    This is completely reworked 
    5865           from the behavior in 1.3, which would instead create a subquery of 
    5866           the entire 
    5867           :class:`_expression.Select` and then join that subquery to the 
    5868           target. 
    5869 
    5870           This is a **backwards incompatible change** as the previous behavior 
    5871           was mostly useless, producing an unnamed subquery rejected by 
    5872           most databases in any case.   The new behavior is modeled after 
    5873           that of the very successful :meth:`_orm.Query.join` method in the 
    5874           ORM, in order to support the functionality of :class:`_orm.Query` 
    5875           being available by using a :class:`_sql.Select` object with an 
    5876           :class:`_orm.Session`. 
    5877 
    5878           See the notes for this change at :ref:`change_select_join`. 
    5879 
    5880        .. seealso:: 
    5881 
    5882            :ref:`tutorial_select_join` - in the :doc:`/tutorial/index` 
    5883 
    5884            :ref:`orm_queryguide_joins` - in the :ref:`queryguide_toplevel` 
    5885 
    5886            :meth:`_expression.Select.join` 
    5887 
    5888        """ 
    5889        return self.join(target, onclause=onclause, isouter=True, full=full) 
    5890 
    5891    def get_final_froms(self) -> Sequence[FromClause]: 
    5892        """Compute the final displayed list of :class:`_expression.FromClause` 
    5893        elements. 
    5894 
    5895        This method will run through the full computation required to 
    5896        determine what FROM elements will be displayed in the resulting 
    5897        SELECT statement, including shadowing individual tables with 
    5898        JOIN objects, as well as full computation for ORM use cases including 
    5899        eager loading clauses. 
    5900 
    5901        For ORM use, this accessor returns the **post compilation** 
    5902        list of FROM objects; this collection will include elements such as 
    5903        eagerly loaded tables and joins.  The objects will **not** be 
    5904        ORM enabled and not work as a replacement for the 
    5905        :meth:`_sql.Select.select_froms` collection; additionally, the 
    5906        method is not well performing for an ORM enabled statement as it 
    5907        will incur the full ORM construction process. 
    5908 
    5909        To retrieve the FROM list that's implied by the "columns" collection 
    5910        passed to the :class:`_sql.Select` originally, use the 
    5911        :attr:`_sql.Select.columns_clause_froms` accessor. 
    5912 
    5913        To select from an alternative set of columns while maintaining the 
    5914        FROM list, use the :meth:`_sql.Select.with_only_columns` method and 
    5915        pass the 
    5916        :paramref:`_sql.Select.with_only_columns.maintain_column_froms` 
    5917        parameter. 
    5918 
    5919        .. versionadded:: 1.4.23 - the :meth:`_sql.Select.get_final_froms` 
    5920           method replaces the previous :attr:`_sql.Select.froms` accessor, 
    5921           which is deprecated. 
    5922 
    5923        .. seealso:: 
    5924 
    5925            :attr:`_sql.Select.columns_clause_froms` 
    5926 
    5927        """ 
    5928        compiler = self._default_compiler() 
    5929 
    5930        return self._compile_state_factory(self, compiler)._get_display_froms() 
    5931 
    5932    @property 
    5933    @util.deprecated( 
    5934        "1.4.23", 
    5935        "The :attr:`_expression.Select.froms` attribute is moved to " 
    5936        "the :meth:`_expression.Select.get_final_froms` method.", 
    5937    ) 
    5938    def froms(self) -> Sequence[FromClause]: 
    5939        """Return the displayed list of :class:`_expression.FromClause` 
    5940        elements. 
    5941 
    5942 
    5943        """ 
    5944        return self.get_final_froms() 
    5945 
    5946    @property 
    5947    def columns_clause_froms(self) -> List[FromClause]: 
    5948        """Return the set of :class:`_expression.FromClause` objects implied 
    5949        by the columns clause of this SELECT statement. 
    5950 
    5951        .. versionadded:: 1.4.23 
    5952 
    5953        .. seealso:: 
    5954 
    5955            :attr:`_sql.Select.froms` - "final" FROM list taking the full 
    5956            statement into account 
    5957 
    5958            :meth:`_sql.Select.with_only_columns` - makes use of this 
    5959            collection to set up a new FROM list 
    5960 
    5961        """ 
    5962 
    5963        return SelectState.get_plugin_class(self).get_columns_clause_froms( 
    5964            self 
    5965        ) 
    5966 
    5967    @property 
    5968    def inner_columns(self) -> _SelectIterable: 
    5969        """An iterator of all :class:`_expression.ColumnElement` 
    5970        expressions which would 
    5971        be rendered into the columns clause of the resulting SELECT statement. 
    5972 
    5973        This method is legacy as of 1.4 and is superseded by the 
    5974        :attr:`_expression.Select.exported_columns` collection. 
    5975 
    5976        """ 
    5977 
    5978        return iter(self._all_selected_columns) 
    5979 
    5980    def is_derived_from(self, fromclause: Optional[FromClause]) -> bool: 
    5981        if fromclause is not None and self in fromclause._cloned_set: 
    5982            return True 
    5983 
    5984        for f in self._iterate_from_elements(): 
    5985            if f.is_derived_from(fromclause): 
    5986                return True 
    5987        return False 
    5988 
    5989    def _copy_internals( 
    5990        self, clone: _CloneCallableType = _clone, **kw: Any 
    5991    ) -> None: 
    5992        # Select() object has been cloned and probably adapted by the 
    5993        # given clone function.  Apply the cloning function to internal 
    5994        # objects 
    5995 
    5996        # 1. keep a dictionary of the froms we've cloned, and what 
    5997        # they've become.  This allows us to ensure the same cloned from 
    5998        # is used when other items such as columns are "cloned" 
    5999 
    6000        all_the_froms = set( 
    6001            itertools.chain( 
    6002                _from_objects(*self._raw_columns), 
    6003                _from_objects(*self._where_criteria), 
    6004                _from_objects(*[elem[0] for elem in self._setup_joins]), 
    6005            ) 
    6006        ) 
    6007 
    6008        # do a clone for the froms we've gathered.  what is important here 
    6009        # is if any of the things we are selecting from, like tables, 
    6010        # were converted into Join objects.   if so, these need to be 
    6011        # added to _from_obj explicitly, because otherwise they won't be 
    6012        # part of the new state, as they don't associate themselves with 
    6013        # their columns. 
    6014        new_froms = {f: clone(f, **kw) for f in all_the_froms} 
    6015 
    6016        # 2. copy FROM collections, adding in joins that we've created. 
    6017        existing_from_obj = [clone(f, **kw) for f in self._from_obj] 
    6018        add_froms = ( 
    6019            {f for f in new_froms.values() if isinstance(f, Join)} 
    6020            .difference(all_the_froms) 
    6021            .difference(existing_from_obj) 
    6022        ) 
    6023 
    6024        self._from_obj = tuple(existing_from_obj) + tuple(add_froms) 
    6025 
    6026        # 3. clone everything else, making sure we use columns 
    6027        # corresponding to the froms we just made. 
    6028        def replace( 
    6029            obj: Union[BinaryExpression[Any], ColumnClause[Any]], 
    6030            **kw: Any, 
    6031        ) -> Optional[KeyedColumnElement[Any]]: 
    6032            if isinstance(obj, ColumnClause) and obj.table in new_froms: 
    6033                newelem = new_froms[obj.table].corresponding_column(obj) 
    6034                return newelem 
    6035            return None 
    6036 
    6037        kw["replace"] = replace 
    6038 
    6039        # copy everything else.   for table-ish things like correlate, 
    6040        # correlate_except, setup_joins, these clone normally.  For 
    6041        # column-expression oriented things like raw_columns, where_criteria, 
    6042        # order by, we get this from the new froms. 
    6043        super()._copy_internals(clone=clone, omit_attrs=("_from_obj",), **kw) 
    6044 
    6045        self._reset_memoizations() 
    6046 
    6047    def get_children(self, **kw: Any) -> Iterable[ClauseElement]: 
    6048        return itertools.chain( 
    6049            super().get_children( 
    6050                omit_attrs=("_from_obj", "_correlate", "_correlate_except"), 
    6051                **kw, 
    6052            ), 
    6053            self._iterate_from_elements(), 
    6054        ) 
    6055 
    6056    @_generative 
    6057    def add_columns( 
    6058        self, *entities: _ColumnsClauseArgument[Any] 
    6059    ) -> Select[Unpack[TupleAny]]: 
    6060        r"""Return a new :func:`_expression.select` construct with 
    6061        the given entities appended to its columns clause. 
    6062 
    6063        E.g.:: 
    6064 
    6065            my_select = my_select.add_columns(table.c.new_column) 
    6066 
    6067        The original expressions in the columns clause remain in place. 
    6068        To replace the original expressions with new ones, see the method 
    6069        :meth:`_expression.Select.with_only_columns`. 
    6070 
    6071        :param \*entities: column, table, or other entity expressions to be 
    6072         added to the columns clause 
    6073 
    6074        .. seealso:: 
    6075 
    6076            :meth:`_expression.Select.with_only_columns` - replaces existing 
    6077            expressions rather than appending. 
    6078 
    6079            :ref:`orm_queryguide_select_multiple_entities` - ORM-centric 
    6080            example 
    6081 
    6082        """ 
    6083        self._reset_memoizations() 
    6084 
    6085        self._raw_columns = self._raw_columns + [ 
    6086            coercions.expect( 
    6087                roles.ColumnsClauseRole, column, apply_propagate_attrs=self 
    6088            ) 
    6089            for column in entities 
    6090        ] 
    6091        return self 
    6092 
    6093    def _set_entities( 
    6094        self, entities: Iterable[_ColumnsClauseArgument[Any]] 
    6095    ) -> None: 
    6096        self._raw_columns = [ 
    6097            coercions.expect( 
    6098                roles.ColumnsClauseRole, ent, apply_propagate_attrs=self 
    6099            ) 
    6100            for ent in util.to_list(entities) 
    6101        ] 
    6102 
    6103    @util.deprecated( 
    6104        "1.4", 
    6105        "The :meth:`_expression.Select.column` method is deprecated and will " 
    6106        "be removed in a future release.  Please use " 
    6107        ":meth:`_expression.Select.add_columns`", 
    6108    ) 
    6109    def column( 
    6110        self, column: _ColumnsClauseArgument[Any] 
    6111    ) -> Select[Unpack[TupleAny]]: 
    6112        """Return a new :func:`_expression.select` construct with 
    6113        the given column expression added to its columns clause. 
    6114 
    6115        E.g.:: 
    6116 
    6117            my_select = my_select.column(table.c.new_column) 
    6118 
    6119        See the documentation for 
    6120        :meth:`_expression.Select.with_only_columns` 
    6121        for guidelines on adding /replacing the columns of a 
    6122        :class:`_expression.Select` object. 
    6123 
    6124        """ 
    6125        return self.add_columns(column) 
    6126 
    6127    @util.preload_module("sqlalchemy.sql.util") 
    6128    def reduce_columns( 
    6129        self, only_synonyms: bool = True 
    6130    ) -> Select[Unpack[TupleAny]]: 
    6131        """Return a new :func:`_expression.select` construct with redundantly 
    6132        named, equivalently-valued columns removed from the columns clause. 
    6133 
    6134        "Redundant" here means two columns where one refers to the 
    6135        other either based on foreign key, or via a simple equality 
    6136        comparison in the WHERE clause of the statement.   The primary purpose 
    6137        of this method is to automatically construct a select statement 
    6138        with all uniquely-named columns, without the need to use 
    6139        table-qualified labels as 
    6140        :meth:`_expression.Select.set_label_style` 
    6141        does. 
    6142 
    6143        When columns are omitted based on foreign key, the referred-to 
    6144        column is the one that's kept.  When columns are omitted based on 
    6145        WHERE equivalence, the first column in the columns clause is the 
    6146        one that's kept. 
    6147 
    6148        :param only_synonyms: when True, limit the removal of columns 
    6149         to those which have the same name as the equivalent.   Otherwise, 
    6150         all columns that are equivalent to another are removed. 
    6151 
    6152        """ 
    6153        woc: Select[Unpack[TupleAny]] 
    6154        woc = self.with_only_columns( 
    6155            *util.preloaded.sql_util.reduce_columns( 
    6156                self._all_selected_columns, 
    6157                only_synonyms=only_synonyms, 
    6158                *(self._where_criteria + self._from_obj), 
    6159            ) 
    6160        ) 
    6161        return woc 
    6162 
    6163    # START OVERLOADED FUNCTIONS self.with_only_columns Select 1-8 ", *, maintain_column_froms: bool =..." # noqa: E501 
    6164 
    6165    # code within this block is **programmatically, 
    6166    # statically generated** by tools/generate_tuple_map_overloads.py 
    6167 
    6168    @overload 
    6169    def with_only_columns( 
    6170        self, __ent0: _TCCA[_T0], /, *, maintain_column_froms: bool = ... 
    6171    ) -> Select[_T0]: ... 
    6172 
    6173    @overload 
    6174    def with_only_columns( 
    6175        self, 
    6176        __ent0: _TCCA[_T0], 
    6177        __ent1: _TCCA[_T1], 
    6178        /, 
    6179        *, 
    6180        maintain_column_froms: bool = ..., 
    6181    ) -> Select[_T0, _T1]: ... 
    6182 
    6183    @overload 
    6184    def with_only_columns( 
    6185        self, 
    6186        __ent0: _TCCA[_T0], 
    6187        __ent1: _TCCA[_T1], 
    6188        __ent2: _TCCA[_T2], 
    6189        /, 
    6190        *, 
    6191        maintain_column_froms: bool = ..., 
    6192    ) -> Select[_T0, _T1, _T2]: ... 
    6193 
    6194    @overload 
    6195    def with_only_columns( 
    6196        self, 
    6197        __ent0: _TCCA[_T0], 
    6198        __ent1: _TCCA[_T1], 
    6199        __ent2: _TCCA[_T2], 
    6200        __ent3: _TCCA[_T3], 
    6201        /, 
    6202        *, 
    6203        maintain_column_froms: bool = ..., 
    6204    ) -> Select[_T0, _T1, _T2, _T3]: ... 
    6205 
    6206    @overload 
    6207    def with_only_columns( 
    6208        self, 
    6209        __ent0: _TCCA[_T0], 
    6210        __ent1: _TCCA[_T1], 
    6211        __ent2: _TCCA[_T2], 
    6212        __ent3: _TCCA[_T3], 
    6213        __ent4: _TCCA[_T4], 
    6214        /, 
    6215        *, 
    6216        maintain_column_froms: bool = ..., 
    6217    ) -> Select[_T0, _T1, _T2, _T3, _T4]: ... 
    6218 
    6219    @overload 
    6220    def with_only_columns( 
    6221        self, 
    6222        __ent0: _TCCA[_T0], 
    6223        __ent1: _TCCA[_T1], 
    6224        __ent2: _TCCA[_T2], 
    6225        __ent3: _TCCA[_T3], 
    6226        __ent4: _TCCA[_T4], 
    6227        __ent5: _TCCA[_T5], 
    6228        /, 
    6229        *, 
    6230        maintain_column_froms: bool = ..., 
    6231    ) -> Select[_T0, _T1, _T2, _T3, _T4, _T5]: ... 
    6232 
    6233    @overload 
    6234    def with_only_columns( 
    6235        self, 
    6236        __ent0: _TCCA[_T0], 
    6237        __ent1: _TCCA[_T1], 
    6238        __ent2: _TCCA[_T2], 
    6239        __ent3: _TCCA[_T3], 
    6240        __ent4: _TCCA[_T4], 
    6241        __ent5: _TCCA[_T5], 
    6242        __ent6: _TCCA[_T6], 
    6243        /, 
    6244        *, 
    6245        maintain_column_froms: bool = ..., 
    6246    ) -> Select[_T0, _T1, _T2, _T3, _T4, _T5, _T6]: ... 
    6247 
    6248    @overload 
    6249    def with_only_columns( 
    6250        self, 
    6251        __ent0: _TCCA[_T0], 
    6252        __ent1: _TCCA[_T1], 
    6253        __ent2: _TCCA[_T2], 
    6254        __ent3: _TCCA[_T3], 
    6255        __ent4: _TCCA[_T4], 
    6256        __ent5: _TCCA[_T5], 
    6257        __ent6: _TCCA[_T6], 
    6258        __ent7: _TCCA[_T7], 
    6259        /, 
    6260        *entities: _ColumnsClauseArgument[Any], 
    6261        maintain_column_froms: bool = ..., 
    6262    ) -> Select[_T0, _T1, _T2, _T3, _T4, _T5, _T6, _T7, Unpack[TupleAny]]: ... 
    6263 
    6264    # END OVERLOADED FUNCTIONS self.with_only_columns 
    6265 
    6266    @overload 
    6267    def with_only_columns( 
    6268        self, 
    6269        *entities: _ColumnsClauseArgument[Any], 
    6270        maintain_column_froms: bool = False, 
    6271        **__kw: Any, 
    6272    ) -> Select[Unpack[TupleAny]]: ... 
    6273 
    6274    @_generative 
    6275    def with_only_columns( 
    6276        self, 
    6277        *entities: _ColumnsClauseArgument[Any], 
    6278        maintain_column_froms: bool = False, 
    6279        **__kw: Any, 
    6280    ) -> Select[Unpack[TupleAny]]: 
    6281        r"""Return a new :func:`_expression.select` construct with its columns 
    6282        clause replaced with the given entities. 
    6283 
    6284        By default, this method is exactly equivalent to as if the original 
    6285        :func:`_expression.select` had been called with the given entities. 
    6286        E.g. a statement:: 
    6287 
    6288            s = select(table1.c.a, table1.c.b) 
    6289            s = s.with_only_columns(table1.c.b) 
    6290 
    6291        should be exactly equivalent to:: 
    6292 
    6293            s = select(table1.c.b) 
    6294 
    6295        In this mode of operation, :meth:`_sql.Select.with_only_columns` 
    6296        will also dynamically alter the FROM clause of the 
    6297        statement if it is not explicitly stated. 
    6298        To maintain the existing set of FROMs including those implied by the 
    6299        current columns clause, add the 
    6300        :paramref:`_sql.Select.with_only_columns.maintain_column_froms` 
    6301        parameter:: 
    6302 
    6303            s = select(table1.c.a, table2.c.b) 
    6304            s = s.with_only_columns(table1.c.a, maintain_column_froms=True) 
    6305 
    6306        The above parameter performs a transfer of the effective FROMs 
    6307        in the columns collection to the :meth:`_sql.Select.select_from` 
    6308        method, as though the following were invoked:: 
    6309 
    6310            s = select(table1.c.a, table2.c.b) 
    6311            s = s.select_from(table1, table2).with_only_columns(table1.c.a) 
    6312 
    6313        The :paramref:`_sql.Select.with_only_columns.maintain_column_froms` 
    6314        parameter makes use of the :attr:`_sql.Select.columns_clause_froms` 
    6315        collection and performs an operation equivalent to the following:: 
    6316 
    6317            s = select(table1.c.a, table2.c.b) 
    6318            s = s.select_from(*s.columns_clause_froms).with_only_columns(table1.c.a) 
    6319 
    6320        :param \*entities: column expressions to be used. 
    6321 
    6322        :param maintain_column_froms: boolean parameter that will ensure the 
    6323         FROM list implied from the current columns clause will be transferred 
    6324         to the :meth:`_sql.Select.select_from` method first. 
    6325 
    6326         .. versionadded:: 1.4.23 
    6327 
    6328        """  # noqa: E501 
    6329 
    6330        if __kw: 
    6331            raise _no_kw() 
    6332 
    6333        # memoizations should be cleared here as of 
    6334        # I95c560ffcbfa30b26644999412fb6a385125f663 , asserting this 
    6335        # is the case for now. 
    6336        self._assert_no_memoizations() 
    6337 
    6338        if maintain_column_froms: 
    6339            self.select_from.non_generative(  # type: ignore 
    6340                self, *self.columns_clause_froms 
    6341            ) 
    6342 
    6343        # then memoize the FROMs etc. 
    6344        _MemoizedSelectEntities._generate_for_statement(self) 
    6345 
    6346        self._raw_columns = [ 
    6347            coercions.expect(roles.ColumnsClauseRole, c) 
    6348            for c in coercions._expression_collection_was_a_list( 
    6349                "entities", "Select.with_only_columns", entities 
    6350            ) 
    6351        ] 
    6352        return self 
    6353 
    6354    @property 
    6355    def whereclause(self) -> Optional[ColumnElement[Any]]: 
    6356        """Return the completed WHERE clause for this 
    6357        :class:`_expression.Select` statement. 
    6358 
    6359        This assembles the current collection of WHERE criteria 
    6360        into a single :class:`_expression.BooleanClauseList` construct. 
    6361 
    6362 
    6363        .. versionadded:: 1.4 
    6364 
    6365        """ 
    6366 
    6367        return BooleanClauseList._construct_for_whereclause( 
    6368            self._where_criteria 
    6369        ) 
    6370 
    6371    _whereclause = whereclause 
    6372 
    6373    @_generative 
    6374    def where(self, *whereclause: _ColumnExpressionArgument[bool]) -> Self: 
    6375        """Return a new :func:`_expression.select` construct with 
    6376        the given expression added to 
    6377        its WHERE clause, joined to the existing clause via AND, if any. 
    6378 
    6379        """ 
    6380 
    6381        assert isinstance(self._where_criteria, tuple) 
    6382 
    6383        for criterion in whereclause: 
    6384            where_criteria: ColumnElement[Any] = coercions.expect( 
    6385                roles.WhereHavingRole, criterion, apply_propagate_attrs=self 
    6386            ) 
    6387            self._where_criteria += (where_criteria,) 
    6388        return self 
    6389 
    6390    @_generative 
    6391    def having(self, *having: _ColumnExpressionArgument[bool]) -> Self: 
    6392        """Return a new :func:`_expression.select` construct with 
    6393        the given expression added to 
    6394        its HAVING clause, joined to the existing clause via AND, if any. 
    6395 
    6396        """ 
    6397 
    6398        for criterion in having: 
    6399            having_criteria = coercions.expect( 
    6400                roles.WhereHavingRole, criterion, apply_propagate_attrs=self 
    6401            ) 
    6402            self._having_criteria += (having_criteria,) 
    6403        return self 
    6404 
    6405    @_generative 
    6406    def distinct(self, *expr: _ColumnExpressionArgument[Any]) -> Self: 
    6407        r"""Return a new :func:`_expression.select` construct which 
    6408        will apply DISTINCT to the SELECT statement overall. 
    6409 
    6410        E.g.:: 
    6411 
    6412            from sqlalchemy import select 
    6413 
    6414            stmt = select(users_table.c.id, users_table.c.name).distinct() 
    6415 
    6416        The above would produce an statement resembling: 
    6417 
    6418        .. sourcecode:: sql 
    6419 
    6420            SELECT DISTINCT user.id, user.name FROM user 
    6421 
    6422        The method also historically accepted an ``*expr`` parameter which 
    6423        produced the PostgreSQL dialect-specific ``DISTINCT ON`` expression. 
    6424        This is now replaced using the :func:`_postgresql.distinct_on` 
    6425        extension:: 
    6426 
    6427            from sqlalchemy import select 
    6428            from sqlalchemy.dialects.postgresql import distinct_on 
    6429 
    6430            stmt = select(users_table).ext(distinct_on(users_table.c.name)) 
    6431 
    6432        Using this parameter on other backends which don't support this 
    6433        syntax will raise an error. 
    6434 
    6435        :param \*expr: optional column expressions.  When present, 
    6436         the PostgreSQL dialect will render a ``DISTINCT ON (<expressions>)`` 
    6437         construct.  A deprecation warning and/or :class:`_exc.CompileError` 
    6438         will be raised on other backends. 
    6439 
    6440         .. deprecated:: 2.1 Passing expressions to 
    6441           :meth:`_sql.Select.distinct` is deprecated, use 
    6442           :func:`_postgresql.distinct_on` instead. 
    6443 
    6444         .. deprecated:: 1.4 Using \*expr in other dialects is deprecated 
    6445            and will raise :class:`_exc.CompileError` in a future version. 
    6446 
    6447        .. seealso:: 
    6448 
    6449            :func:`_postgresql.distinct_on` 
    6450 
    6451            :meth:`_sql.HasSyntaxExtensions.ext` 
    6452        """ 
    6453        self._distinct = True 
    6454        if expr: 
    6455            warn_deprecated( 
    6456                "Passing expression to ``distinct`` to generate a " 
    6457                "DISTINCT ON clause is deprecated. Use instead the " 
    6458                "``postgresql.distinct_on`` function as an extension.", 
    6459                "2.1", 
    6460            ) 
    6461            self._distinct_on = self._distinct_on + tuple( 
    6462                coercions.expect(roles.ByOfRole, e, apply_propagate_attrs=self) 
    6463                for e in expr 
    6464            ) 
    6465        return self 
    6466 
    6467    @_generative 
    6468    def select_from(self, *froms: _FromClauseArgument) -> Self: 
    6469        r"""Return a new :func:`_expression.select` construct with the 
    6470        given FROM expression(s) 
    6471        merged into its list of FROM objects. 
    6472 
    6473        E.g.:: 
    6474 
    6475            table1 = table("t1", column("a")) 
    6476            table2 = table("t2", column("b")) 
    6477            s = select(table1.c.a).select_from( 
    6478                table1.join(table2, table1.c.a == table2.c.b) 
    6479            ) 
    6480 
    6481        The "from" list is a unique set on the identity of each element, 
    6482        so adding an already present :class:`_schema.Table` 
    6483        or other selectable 
    6484        will have no effect.   Passing a :class:`_expression.Join` that refers 
    6485        to an already present :class:`_schema.Table` 
    6486        or other selectable will have 
    6487        the effect of concealing the presence of that selectable as 
    6488        an individual element in the rendered FROM list, instead 
    6489        rendering it into a JOIN clause. 
    6490 
    6491        While the typical purpose of :meth:`_expression.Select.select_from` 
    6492        is to 
    6493        replace the default, derived FROM clause with a join, it can 
    6494        also be called with individual table elements, multiple times 
    6495        if desired, in the case that the FROM clause cannot be fully 
    6496        derived from the columns clause:: 
    6497 
    6498            select(func.count("*")).select_from(table1) 
    6499 
    6500        """ 
    6501 
    6502        self._from_obj += tuple( 
    6503            coercions.expect( 
    6504                roles.FromClauseRole, fromclause, apply_propagate_attrs=self 
    6505            ) 
    6506            for fromclause in froms 
    6507        ) 
    6508        return self 
    6509 
    6510    @_generative 
    6511    def correlate( 
    6512        self, 
    6513        *fromclauses: Union[Literal[None, False], _FromClauseArgument], 
    6514    ) -> Self: 
    6515        r"""Return a new :class:`_expression.Select` 
    6516        which will correlate the given FROM 
    6517        clauses to that of an enclosing :class:`_expression.Select`. 
    6518 
    6519        Calling this method turns off the :class:`_expression.Select` object's 
    6520        default behavior of "auto-correlation".  Normally, FROM elements 
    6521        which appear in a :class:`_expression.Select` 
    6522        that encloses this one via 
    6523        its :term:`WHERE clause`, ORDER BY, HAVING or 
    6524        :term:`columns clause` will be omitted from this 
    6525        :class:`_expression.Select` 
    6526        object's :term:`FROM clause`. 
    6527        Setting an explicit correlation collection using the 
    6528        :meth:`_expression.Select.correlate` 
    6529        method provides a fixed list of FROM objects 
    6530        that can potentially take place in this process. 
    6531 
    6532        When :meth:`_expression.Select.correlate` 
    6533        is used to apply specific FROM clauses 
    6534        for correlation, the FROM elements become candidates for 
    6535        correlation regardless of how deeply nested this 
    6536        :class:`_expression.Select` 
    6537        object is, relative to an enclosing :class:`_expression.Select` 
    6538        which refers to 
    6539        the same FROM object.  This is in contrast to the behavior of 
    6540        "auto-correlation" which only correlates to an immediate enclosing 
    6541        :class:`_expression.Select`. 
    6542        Multi-level correlation ensures that the link 
    6543        between enclosed and enclosing :class:`_expression.Select` 
    6544        is always via 
    6545        at least one WHERE/ORDER BY/HAVING/columns clause in order for 
    6546        correlation to take place. 
    6547 
    6548        If ``None`` is passed, the :class:`_expression.Select` 
    6549        object will correlate 
    6550        none of its FROM entries, and all will render unconditionally 
    6551        in the local FROM clause. 
    6552 
    6553        :param \*fromclauses: one or more :class:`.FromClause` or other 
    6554         FROM-compatible construct such as an ORM mapped entity to become part 
    6555         of the correlate collection; alternatively pass a single value 
    6556         ``None`` to remove all existing correlations. 
    6557 
    6558        .. seealso:: 
    6559 
    6560            :meth:`_expression.Select.correlate_except` 
    6561 
    6562            :ref:`tutorial_scalar_subquery` 
    6563 
    6564        """ 
    6565 
    6566        # tests failing when we try to change how these 
    6567        # arguments are passed 
    6568 
    6569        self._auto_correlate = False 
    6570        if not fromclauses or fromclauses[0] in {None, False}: 
    6571            if len(fromclauses) > 1: 
    6572                raise exc.ArgumentError( 
    6573                    "additional FROM objects not accepted when " 
    6574                    "passing None/False to correlate()" 
    6575                ) 
    6576            self._correlate = () 
    6577        else: 
    6578            self._correlate = self._correlate + tuple( 
    6579                coercions.expect(roles.FromClauseRole, f) for f in fromclauses 
    6580            ) 
    6581        return self 
    6582 
    6583    @_generative 
    6584    def correlate_except( 
    6585        self, 
    6586        *fromclauses: Union[Literal[None, False], _FromClauseArgument], 
    6587    ) -> Self: 
    6588        r"""Return a new :class:`_expression.Select` 
    6589        which will omit the given FROM 
    6590        clauses from the auto-correlation process. 
    6591 
    6592        Calling :meth:`_expression.Select.correlate_except` turns off the 
    6593        :class:`_expression.Select` object's default behavior of 
    6594        "auto-correlation" for the given FROM elements.  An element 
    6595        specified here will unconditionally appear in the FROM list, while 
    6596        all other FROM elements remain subject to normal auto-correlation 
    6597        behaviors. 
    6598 
    6599        If ``None`` is passed, or no arguments are passed, 
    6600        the :class:`_expression.Select` object will correlate all of its 
    6601        FROM entries. 
    6602 
    6603        :param \*fromclauses: a list of one or more 
    6604         :class:`_expression.FromClause` 
    6605         constructs, or other compatible constructs (i.e. ORM-mapped 
    6606         classes) to become part of the correlate-exception collection. 
    6607 
    6608        .. seealso:: 
    6609 
    6610            :meth:`_expression.Select.correlate` 
    6611 
    6612            :ref:`tutorial_scalar_subquery` 
    6613 
    6614        """ 
    6615 
    6616        self._auto_correlate = False 
    6617        if not fromclauses or fromclauses[0] in {None, False}: 
    6618            if len(fromclauses) > 1: 
    6619                raise exc.ArgumentError( 
    6620                    "additional FROM objects not accepted when " 
    6621                    "passing None/False to correlate_except()" 
    6622                ) 
    6623            self._correlate_except = () 
    6624        else: 
    6625            self._correlate_except = (self._correlate_except or ()) + tuple( 
    6626                coercions.expect(roles.FromClauseRole, f) for f in fromclauses 
    6627            ) 
    6628 
    6629        return self 
    6630 
    6631    @HasMemoized_ro_memoized_attribute 
    6632    def selected_columns( 
    6633        self, 
    6634    ) -> ColumnCollection[str, ColumnElement[Any]]: 
    6635        """A :class:`_expression.ColumnCollection` 
    6636        representing the columns that 
    6637        this SELECT statement or similar construct returns in its result set, 
    6638        not including :class:`_sql.TextClause` constructs. 
    6639 
    6640        This collection differs from the :attr:`_expression.FromClause.columns` 
    6641        collection of a :class:`_expression.FromClause` in that the columns 
    6642        within this collection cannot be directly nested inside another SELECT 
    6643        statement; a subquery must be applied first which provides for the 
    6644        necessary parenthesization required by SQL. 
    6645 
    6646        For a :func:`_expression.select` construct, the collection here is 
    6647        exactly what would be rendered inside the "SELECT" statement, and the 
    6648        :class:`_expression.ColumnElement` objects are directly present as they 
    6649        were given, e.g.:: 
    6650 
    6651            col1 = column("q", Integer) 
    6652            col2 = column("p", Integer) 
    6653            stmt = select(col1, col2) 
    6654 
    6655        Above, ``stmt.selected_columns`` would be a collection that contains 
    6656        the ``col1`` and ``col2`` objects directly. For a statement that is 
    6657        against a :class:`_schema.Table` or other 
    6658        :class:`_expression.FromClause`, the collection will use the 
    6659        :class:`_expression.ColumnElement` objects that are in the 
    6660        :attr:`_expression.FromClause.c` collection of the from element. 
    6661 
    6662        A use case for the :attr:`_sql.Select.selected_columns` collection is 
    6663        to allow the existing columns to be referenced when adding additional 
    6664        criteria, e.g.:: 
    6665 
    6666            def filter_on_id(my_select, id): 
    6667                return my_select.where(my_select.selected_columns["id"] == id) 
    6668 
    6669 
    6670            stmt = select(MyModel) 
    6671 
    6672            # adds "WHERE id=:param" to the statement 
    6673            stmt = filter_on_id(stmt, 42) 
    6674 
    6675        .. note:: 
    6676 
    6677            The :attr:`_sql.Select.selected_columns` collection does not 
    6678            include expressions established in the columns clause using the 
    6679            :func:`_sql.text` construct; these are silently omitted from the 
    6680            collection. To use plain textual column expressions inside of a 
    6681            :class:`_sql.Select` construct, use the :func:`_sql.literal_column` 
    6682            construct. 
    6683 
    6684 
    6685        .. versionadded:: 1.4 
    6686 
    6687        """ 
    6688 
    6689        # compare to SelectState._generate_columns_plus_names, which 
    6690        # generates the actual names used in the SELECT string.  that 
    6691        # method is more complex because it also renders columns that are 
    6692        # fully ambiguous, e.g. same column more than once. 
    6693        conv = cast( 
    6694            "Callable[[Any], str]", 
    6695            SelectState._column_naming_convention(self._label_style), 
    6696        ) 
    6697 
    6698        cc: ColumnCollection[str, ColumnElement[Any]] = ColumnCollection( 
    6699            [ 
    6700                (conv(c), c) 
    6701                for c in self._all_selected_columns 
    6702                if is_column_element(c) 
    6703            ] 
    6704        ) 
    6705        return cc.as_readonly() 
    6706 
    6707    @HasMemoized_ro_memoized_attribute 
    6708    def _all_selected_columns(self) -> _SelectIterable: 
    6709        meth = SelectState.get_plugin_class(self).all_selected_columns 
    6710        return list(meth(self)) 
    6711 
    6712    def _ensure_disambiguated_names(self) -> Select[Unpack[TupleAny]]: 
    6713        if self._label_style is LABEL_STYLE_NONE: 
    6714            self = self.set_label_style(LABEL_STYLE_DISAMBIGUATE_ONLY) 
    6715        return self 
    6716 
    6717    def _generate_fromclause_column_proxies( 
    6718        self, 
    6719        subquery: FromClause, 
    6720        columns: ColumnCollection[str, KeyedColumnElement[Any]], 
    6721        primary_key: ColumnSet, 
    6722        foreign_keys: Set[KeyedColumnElement[Any]], 
    6723        *, 
    6724        proxy_compound_columns: Optional[ 
    6725            Iterable[Sequence[ColumnElement[Any]]] 
    6726        ] = None, 
    6727    ) -> None: 
    6728        """Generate column proxies to place in the exported ``.c`` 
    6729        collection of a subquery.""" 
    6730 
    6731        if proxy_compound_columns: 
    6732            extra_col_iterator = proxy_compound_columns 
    6733            prox = [ 
    6734                c._make_proxy( 
    6735                    subquery, 
    6736                    key=proxy_key, 
    6737                    name=required_label_name, 
    6738                    name_is_truncatable=True, 
    6739                    compound_select_cols=extra_cols, 
    6740                    primary_key=primary_key, 
    6741                    foreign_keys=foreign_keys, 
    6742                ) 
    6743                for ( 
    6744                    ( 
    6745                        required_label_name, 
    6746                        proxy_key, 
    6747                        fallback_label_name, 
    6748                        c, 
    6749                        repeated, 
    6750                    ), 
    6751                    extra_cols, 
    6752                ) in ( 
    6753                    zip( 
    6754                        self._generate_columns_plus_names(False), 
    6755                        extra_col_iterator, 
    6756                    ) 
    6757                ) 
    6758                if is_column_element(c) 
    6759            ] 
    6760        else: 
    6761            prox = [ 
    6762                c._make_proxy( 
    6763                    subquery, 
    6764                    key=proxy_key, 
    6765                    name=required_label_name, 
    6766                    name_is_truncatable=True, 
    6767                    primary_key=primary_key, 
    6768                    foreign_keys=foreign_keys, 
    6769                ) 
    6770                for ( 
    6771                    required_label_name, 
    6772                    proxy_key, 
    6773                    fallback_label_name, 
    6774                    c, 
    6775                    repeated, 
    6776                ) in (self._generate_columns_plus_names(False)) 
    6777                if is_column_element(c) 
    6778            ] 
    6779 
    6780        columns._populate_separate_keys(prox) 
    6781 
    6782    def _needs_parens_for_grouping(self) -> bool: 
    6783        return self._has_row_limiting_clause or bool( 
    6784            self._order_by_clause.clauses 
    6785        ) 
    6786 
    6787    def self_group( 
    6788        self, against: Optional[OperatorType] = None 
    6789    ) -> Union[SelectStatementGrouping[Self], Self]: 
    6790        """Return a 'grouping' construct as per the 
    6791        :class:`_expression.ClauseElement` specification. 
    6792 
    6793        This produces an element that can be embedded in an expression. Note 
    6794        that this method is called automatically as needed when constructing 
    6795        expressions and should not require explicit use. 
    6796 
    6797        """ 
    6798        if ( 
    6799            isinstance(against, CompoundSelect) 
    6800            and not self._needs_parens_for_grouping() 
    6801        ): 
    6802            return self 
    6803        else: 
    6804            return SelectStatementGrouping(self) 
    6805 
    6806    def union( 
    6807        self, *other: _SelectStatementForCompoundArgument[Unpack[_Ts]] 
    6808    ) -> CompoundSelect[Unpack[_Ts]]: 
    6809        r"""Return a SQL ``UNION`` of this select() construct against 
    6810        the given selectables provided as positional arguments. 
    6811 
    6812        :param \*other: one or more elements with which to create a 
    6813         UNION. 
    6814 
    6815         .. versionchanged:: 1.4.28 
    6816 
    6817            multiple elements are now accepted. 
    6818 
    6819        :param \**kwargs: keyword arguments are forwarded to the constructor 
    6820         for the newly created :class:`_sql.CompoundSelect` object. 
    6821 
    6822        """ 
    6823        return CompoundSelect._create_union(self, *other) 
    6824 
    6825    def union_all( 
    6826        self, *other: _SelectStatementForCompoundArgument[Unpack[_Ts]] 
    6827    ) -> CompoundSelect[Unpack[_Ts]]: 
    6828        r"""Return a SQL ``UNION ALL`` of this select() construct against 
    6829        the given selectables provided as positional arguments. 
    6830 
    6831        :param \*other: one or more elements with which to create a 
    6832         UNION. 
    6833 
    6834         .. versionchanged:: 1.4.28 
    6835 
    6836            multiple elements are now accepted. 
    6837 
    6838        :param \**kwargs: keyword arguments are forwarded to the constructor 
    6839         for the newly created :class:`_sql.CompoundSelect` object. 
    6840 
    6841        """ 
    6842        return CompoundSelect._create_union_all(self, *other) 
    6843 
    6844    def except_( 
    6845        self, *other: _SelectStatementForCompoundArgument[Unpack[_Ts]] 
    6846    ) -> CompoundSelect[Unpack[_Ts]]: 
    6847        r"""Return a SQL ``EXCEPT`` of this select() construct against 
    6848        the given selectable provided as positional arguments. 
    6849 
    6850        :param \*other: one or more elements with which to create a 
    6851         UNION. 
    6852 
    6853         .. versionchanged:: 1.4.28 
    6854 
    6855            multiple elements are now accepted. 
    6856 
    6857        """ 
    6858        return CompoundSelect._create_except(self, *other) 
    6859 
    6860    def except_all( 
    6861        self, *other: _SelectStatementForCompoundArgument[Unpack[_Ts]] 
    6862    ) -> CompoundSelect[Unpack[_Ts]]: 
    6863        r"""Return a SQL ``EXCEPT ALL`` of this select() construct against 
    6864        the given selectables provided as positional arguments. 
    6865 
    6866        :param \*other: one or more elements with which to create a 
    6867         UNION. 
    6868 
    6869         .. versionchanged:: 1.4.28 
    6870 
    6871            multiple elements are now accepted. 
    6872 
    6873        """ 
    6874        return CompoundSelect._create_except_all(self, *other) 
    6875 
    6876    def intersect( 
    6877        self, *other: _SelectStatementForCompoundArgument[Unpack[_Ts]] 
    6878    ) -> CompoundSelect[Unpack[_Ts]]: 
    6879        r"""Return a SQL ``INTERSECT`` of this select() construct against 
    6880        the given selectables provided as positional arguments. 
    6881 
    6882        :param \*other: one or more elements with which to create a 
    6883         UNION. 
    6884 
    6885         .. versionchanged:: 1.4.28 
    6886 
    6887            multiple elements are now accepted. 
    6888 
    6889        :param \**kwargs: keyword arguments are forwarded to the constructor 
    6890         for the newly created :class:`_sql.CompoundSelect` object. 
    6891 
    6892        """ 
    6893        return CompoundSelect._create_intersect(self, *other) 
    6894 
    6895    def intersect_all( 
    6896        self, *other: _SelectStatementForCompoundArgument[Unpack[_Ts]] 
    6897    ) -> CompoundSelect[Unpack[_Ts]]: 
    6898        r"""Return a SQL ``INTERSECT ALL`` of this select() construct 
    6899        against the given selectables provided as positional arguments. 
    6900 
    6901        :param \*other: one or more elements with which to create a 
    6902         UNION. 
    6903 
    6904         .. versionchanged:: 1.4.28 
    6905 
    6906            multiple elements are now accepted. 
    6907 
    6908        :param \**kwargs: keyword arguments are forwarded to the constructor 
    6909         for the newly created :class:`_sql.CompoundSelect` object. 
    6910 
    6911        """ 
    6912        return CompoundSelect._create_intersect_all(self, *other) 
    6913 
    6914 
    6915class ScalarSelect( 
    6916    roles.InElementRole, Generative, GroupedElement, ColumnElement[_T] 
    6917): 
    6918    """Represent a scalar subquery. 
    6919 
    6920 
    6921    A :class:`_sql.ScalarSelect` is created by invoking the 
    6922    :meth:`_sql.SelectBase.scalar_subquery` method.   The object 
    6923    then participates in other SQL expressions as a SQL column expression 
    6924    within the :class:`_sql.ColumnElement` hierarchy. 
    6925 
    6926    .. seealso:: 
    6927 
    6928        :meth:`_sql.SelectBase.scalar_subquery` 
    6929 
    6930        :ref:`tutorial_scalar_subquery` - in the 2.0 tutorial 
    6931 
    6932    """ 
    6933 
    6934    _traverse_internals: _TraverseInternalsType = [ 
    6935        ("element", InternalTraversal.dp_clauseelement), 
    6936        ("type", InternalTraversal.dp_type), 
    6937    ] 
    6938 
    6939    _from_objects: List[FromClause] = [] 
    6940    _is_from_container = True 
    6941    if not TYPE_CHECKING: 
    6942        _is_implicitly_boolean = False 
    6943    inherit_cache = True 
    6944 
    6945    element: SelectBase 
    6946 
    6947    def __init__(self, element: SelectBase) -> None: 
    6948        self.element = element 
    6949        self.type = element._scalar_type() 
    6950        self._propagate_attrs = element._propagate_attrs 
    6951 
    6952    def __getattr__(self, attr: str) -> Any: 
    6953        return getattr(self.element, attr) 
    6954 
    6955    def __getstate__(self) -> Dict[str, Any]: 
    6956        return {"element": self.element, "type": self.type} 
    6957 
    6958    def __setstate__(self, state: Dict[str, Any]) -> None: 
    6959        self.element = state["element"] 
    6960        self.type = state["type"] 
    6961 
    6962    @property 
    6963    def columns(self) -> NoReturn: 
    6964        raise exc.InvalidRequestError( 
    6965            "Scalar Select expression has no " 
    6966            "columns; use this object directly " 
    6967            "within a column-level expression." 
    6968        ) 
    6969 
    6970    c = columns 
    6971 
    6972    @_generative 
    6973    def where(self, crit: _ColumnExpressionArgument[bool]) -> Self: 
    6974        """Apply a WHERE clause to the SELECT statement referred to 
    6975        by this :class:`_expression.ScalarSelect`. 
    6976 
    6977        """ 
    6978        self.element = cast("Select[Unpack[TupleAny]]", self.element).where( 
    6979            crit 
    6980        ) 
    6981        return self 
    6982 
    6983    def self_group(self, against: Optional[OperatorType] = None) -> Self: 
    6984        return self 
    6985 
    6986    def _ungroup(self) -> Self: 
    6987        return self 
    6988 
    6989    @_generative 
    6990    def correlate( 
    6991        self, 
    6992        *fromclauses: Union[Literal[None, False], _FromClauseArgument], 
    6993    ) -> Self: 
    6994        r"""Return a new :class:`_expression.ScalarSelect` 
    6995        which will correlate the given FROM 
    6996        clauses to that of an enclosing :class:`_expression.Select`. 
    6997 
    6998        This method is mirrored from the :meth:`_sql.Select.correlate` method 
    6999        of the underlying :class:`_sql.Select`.  The method applies the 
    7000        :meth:_sql.Select.correlate` method, then returns a new 
    7001        :class:`_sql.ScalarSelect` against that statement. 
    7002 
    7003        .. versionadded:: 1.4 Previously, the 
    7004           :meth:`_sql.ScalarSelect.correlate` 
    7005           method was only available from :class:`_sql.Select`. 
    7006 
    7007        :param \*fromclauses: a list of one or more 
    7008         :class:`_expression.FromClause` 
    7009         constructs, or other compatible constructs (i.e. ORM-mapped 
    7010         classes) to become part of the correlate collection. 
    7011 
    7012        .. seealso:: 
    7013 
    7014            :meth:`_expression.ScalarSelect.correlate_except` 
    7015 
    7016            :ref:`tutorial_scalar_subquery` - in the 2.0 tutorial 
    7017 
    7018 
    7019        """ 
    7020        self.element = cast( 
    7021            "Select[Unpack[TupleAny]]", self.element 
    7022        ).correlate(*fromclauses) 
    7023        return self 
    7024 
    7025    @_generative 
    7026    def correlate_except( 
    7027        self, 
    7028        *fromclauses: Union[Literal[None, False], _FromClauseArgument], 
    7029    ) -> Self: 
    7030        r"""Return a new :class:`_expression.ScalarSelect` 
    7031        which will omit the given FROM 
    7032        clauses from the auto-correlation process. 
    7033 
    7034        This method is mirrored from the 
    7035        :meth:`_sql.Select.correlate_except` method of the underlying 
    7036        :class:`_sql.Select`.  The method applies the 
    7037        :meth:_sql.Select.correlate_except` method, then returns a new 
    7038        :class:`_sql.ScalarSelect` against that statement. 
    7039 
    7040        .. versionadded:: 1.4 Previously, the 
    7041           :meth:`_sql.ScalarSelect.correlate_except` 
    7042           method was only available from :class:`_sql.Select`. 
    7043 
    7044        :param \*fromclauses: a list of one or more 
    7045         :class:`_expression.FromClause` 
    7046         constructs, or other compatible constructs (i.e. ORM-mapped 
    7047         classes) to become part of the correlate-exception collection. 
    7048 
    7049        .. seealso:: 
    7050 
    7051            :meth:`_expression.ScalarSelect.correlate` 
    7052 
    7053            :ref:`tutorial_scalar_subquery` - in the 2.0 tutorial 
    7054 
    7055 
    7056        """ 
    7057 
    7058        self.element = cast( 
    7059            "Select[Unpack[TupleAny]]", self.element 
    7060        ).correlate_except(*fromclauses) 
    7061        return self 
    7062 
    7063 
    7064class Exists(UnaryExpression[bool]): 
    7065    """Represent an ``EXISTS`` clause. 
    7066 
    7067    See :func:`_sql.exists` for a description of usage. 
    7068 
    7069    An ``EXISTS`` clause can also be constructed from a :func:`_sql.select` 
    7070    instance by calling :meth:`_sql.SelectBase.exists`. 
    7071 
    7072    """ 
    7073 
    7074    inherit_cache = True 
    7075 
    7076    def __init__( 
    7077        self, 
    7078        __argument: Optional[ 
    7079            Union[_ColumnsClauseArgument[Any], SelectBase, ScalarSelect[Any]] 
    7080        ] = None, 
    7081        /, 
    7082    ): 
    7083        s: ScalarSelect[Any] 
    7084 
    7085        # TODO: this seems like we should be using coercions for this 
    7086        if __argument is None: 
    7087            s = Select(literal_column("*")).scalar_subquery() 
    7088        elif isinstance(__argument, SelectBase): 
    7089            s = __argument.scalar_subquery() 
    7090            s._propagate_attrs = __argument._propagate_attrs 
    7091        elif isinstance(__argument, ScalarSelect): 
    7092            s = __argument 
    7093        else: 
    7094            s = Select(__argument).scalar_subquery() 
    7095 
    7096        UnaryExpression.__init__( 
    7097            self, 
    7098            s, 
    7099            operator=operators.exists, 
    7100            type_=type_api.BOOLEANTYPE, 
    7101        ) 
    7102 
    7103    @util.ro_non_memoized_property 
    7104    def _from_objects(self) -> List[FromClause]: 
    7105        return [] 
    7106 
    7107    def _regroup( 
    7108        self, 
    7109        fn: Callable[[Select[Unpack[TupleAny]]], Select[Unpack[TupleAny]]], 
    7110    ) -> ScalarSelect[Any]: 
    7111 
    7112        assert isinstance(self.element, ScalarSelect) 
    7113        element = self.element.element 
    7114        if not isinstance(element, Select): 
    7115            raise exc.InvalidRequestError( 
    7116                "Can only apply this operation to a plain SELECT construct" 
    7117            ) 
    7118        new_element = fn(element) 
    7119 
    7120        return_value = new_element.scalar_subquery() 
    7121        return return_value 
    7122 
    7123    def select(self) -> Select[bool]: 
    7124        r"""Return a SELECT of this :class:`_expression.Exists`. 
    7125 
    7126        e.g.:: 
    7127 
    7128            stmt = exists(some_table.c.id).where(some_table.c.id == 5).select() 
    7129 
    7130        This will produce a statement resembling: 
    7131 
    7132        .. sourcecode:: sql 
    7133 
    7134            SELECT EXISTS (SELECT id FROM some_table WHERE some_table = :param) AS anon_1 
    7135 
    7136        .. seealso:: 
    7137 
    7138            :func:`_expression.select` - general purpose 
    7139            method which allows for arbitrary column lists. 
    7140 
    7141        """  # noqa 
    7142 
    7143        return Select(self) 
    7144 
    7145    def correlate( 
    7146        self, 
    7147        *fromclauses: Union[Literal[None, False], _FromClauseArgument], 
    7148    ) -> Self: 
    7149        """Apply correlation to the subquery noted by this 
    7150        :class:`_sql.Exists`. 
    7151 
    7152        .. seealso:: 
    7153 
    7154            :meth:`_sql.ScalarSelect.correlate` 
    7155 
    7156        """ 
    7157        e = self._clone() 
    7158        e.element = self._regroup( 
    7159            lambda element: element.correlate(*fromclauses) 
    7160        ) 
    7161        return e 
    7162 
    7163    def correlate_except( 
    7164        self, 
    7165        *fromclauses: Union[Literal[None, False], _FromClauseArgument], 
    7166    ) -> Self: 
    7167        """Apply correlation to the subquery noted by this 
    7168        :class:`_sql.Exists`. 
    7169 
    7170        .. seealso:: 
    7171 
    7172            :meth:`_sql.ScalarSelect.correlate_except` 
    7173 
    7174        """ 
    7175        e = self._clone() 
    7176        e.element = self._regroup( 
    7177            lambda element: element.correlate_except(*fromclauses) 
    7178        ) 
    7179        return e 
    7180 
    7181    def select_from(self, *froms: _FromClauseArgument) -> Self: 
    7182        """Return a new :class:`_expression.Exists` construct, 
    7183        applying the given 
    7184        expression to the :meth:`_expression.Select.select_from` 
    7185        method of the select 
    7186        statement contained. 
    7187 
    7188        .. note:: it is typically preferable to build a :class:`_sql.Select` 
    7189           statement first, including the desired WHERE clause, then use the 
    7190           :meth:`_sql.SelectBase.exists` method to produce an 
    7191           :class:`_sql.Exists` object at once. 
    7192 
    7193        """ 
    7194        e = self._clone() 
    7195        e.element = self._regroup(lambda element: element.select_from(*froms)) 
    7196        return e 
    7197 
    7198    def where(self, *clause: _ColumnExpressionArgument[bool]) -> Self: 
    7199        """Return a new :func:`_expression.exists` construct with the 
    7200        given expression added to 
    7201        its WHERE clause, joined to the existing clause via AND, if any. 
    7202 
    7203 
    7204        .. note:: it is typically preferable to build a :class:`_sql.Select` 
    7205           statement first, including the desired WHERE clause, then use the 
    7206           :meth:`_sql.SelectBase.exists` method to produce an 
    7207           :class:`_sql.Exists` object at once. 
    7208 
    7209        """ 
    7210        e = self._clone() 
    7211        e.element = self._regroup(lambda element: element.where(*clause)) 
    7212        return e 
    7213 
    7214 
    7215class TextualSelect(SelectBase, ExecutableReturnsRows, Generative): 
    7216    """Wrap a :class:`_expression.TextClause` construct within a 
    7217    :class:`_expression.SelectBase` 
    7218    interface. 
    7219 
    7220    This allows the :class:`_expression.TextClause` object to gain a 
    7221    ``.c`` collection 
    7222    and other FROM-like capabilities such as 
    7223    :meth:`_expression.FromClause.alias`, 
    7224    :meth:`_expression.SelectBase.cte`, etc. 
    7225 
    7226    The :class:`_expression.TextualSelect` construct is produced via the 
    7227    :meth:`_expression.TextClause.columns` 
    7228    method - see that method for details. 
    7229 
    7230    .. versionchanged:: 1.4 the :class:`_expression.TextualSelect` 
    7231       class was renamed 
    7232       from ``TextAsFrom``, to more correctly suit its role as a 
    7233       SELECT-oriented object and not a FROM clause. 
    7234 
    7235    .. seealso:: 
    7236 
    7237        :func:`_expression.text` 
    7238 
    7239        :meth:`_expression.TextClause.columns` - primary creation interface. 
    7240 
    7241    """ 
    7242 
    7243    __visit_name__ = "textual_select" 
    7244 
    7245    _label_style = LABEL_STYLE_NONE 
    7246 
    7247    _traverse_internals: _TraverseInternalsType = ( 
    7248        [ 
    7249            ("element", InternalTraversal.dp_clauseelement), 
    7250            ("column_args", InternalTraversal.dp_clauseelement_list), 
    7251        ] 
    7252        + SupportsCloneAnnotations._clone_annotations_traverse_internals 
    7253        + HasCTE._has_ctes_traverse_internals 
    7254        + Executable._executable_traverse_internals 
    7255    ) 
    7256 
    7257    _is_textual = True 
    7258 
    7259    is_text = True 
    7260    is_select = True 
    7261 
    7262    def __init__( 
    7263        self, 
    7264        text: TextClause, 
    7265        columns: List[_ColumnExpressionArgument[Any]], 
    7266        positional: bool = False, 
    7267    ) -> None: 
    7268        self._init( 
    7269            text, 
    7270            # convert for ORM attributes->columns, etc 
    7271            [ 
    7272                coercions.expect(roles.LabeledColumnExprRole, c) 
    7273                for c in columns 
    7274            ], 
    7275            positional, 
    7276        ) 
    7277 
    7278    def _init( 
    7279        self, 
    7280        text: TextClause, 
    7281        columns: List[NamedColumn[Any]], 
    7282        positional: bool = False, 
    7283    ) -> None: 
    7284        self.element = text 
    7285        self.column_args = columns 
    7286        self.positional = positional 
    7287 
    7288    @HasMemoized_ro_memoized_attribute 
    7289    def selected_columns( 
    7290        self, 
    7291    ) -> ColumnCollection[str, KeyedColumnElement[Any]]: 
    7292        """A :class:`_expression.ColumnCollection` 
    7293        representing the columns that 
    7294        this SELECT statement or similar construct returns in its result set, 
    7295        not including :class:`_sql.TextClause` constructs. 
    7296 
    7297        This collection differs from the :attr:`_expression.FromClause.columns` 
    7298        collection of a :class:`_expression.FromClause` in that the columns 
    7299        within this collection cannot be directly nested inside another SELECT 
    7300        statement; a subquery must be applied first which provides for the 
    7301        necessary parenthesization required by SQL. 
    7302 
    7303        For a :class:`_expression.TextualSelect` construct, the collection 
    7304        contains the :class:`_expression.ColumnElement` objects that were 
    7305        passed to the constructor, typically via the 
    7306        :meth:`_expression.TextClause.columns` method. 
    7307 
    7308 
    7309        .. versionadded:: 1.4 
    7310 
    7311        """ 
    7312        return ColumnCollection( 
    7313            (c.key, c) for c in self.column_args 
    7314        ).as_readonly() 
    7315 
    7316    @util.ro_non_memoized_property 
    7317    def _all_selected_columns(self) -> _SelectIterable: 
    7318        return self.column_args 
    7319 
    7320    def set_label_style(self, style: SelectLabelStyle) -> TextualSelect: 
    7321        return self 
    7322 
    7323    def _ensure_disambiguated_names(self) -> TextualSelect: 
    7324        return self 
    7325 
    7326    @_generative 
    7327    def bindparams( 
    7328        self, 
    7329        *binds: BindParameter[Any], 
    7330        **bind_as_values: Any, 
    7331    ) -> Self: 
    7332        self.element = self.element.bindparams(*binds, **bind_as_values) 
    7333        return self 
    7334 
    7335    def _generate_fromclause_column_proxies( 
    7336        self, 
    7337        fromclause: FromClause, 
    7338        columns: ColumnCollection[str, KeyedColumnElement[Any]], 
    7339        primary_key: ColumnSet, 
    7340        foreign_keys: Set[KeyedColumnElement[Any]], 
    7341        *, 
    7342        proxy_compound_columns: Optional[ 
    7343            Iterable[Sequence[ColumnElement[Any]]] 
    7344        ] = None, 
    7345    ) -> None: 
    7346        if TYPE_CHECKING: 
    7347            assert isinstance(fromclause, Subquery) 
    7348 
    7349        if proxy_compound_columns: 
    7350            columns._populate_separate_keys( 
    7351                c._make_proxy( 
    7352                    fromclause, 
    7353                    compound_select_cols=extra_cols, 
    7354                    primary_key=primary_key, 
    7355                    foreign_keys=foreign_keys, 
    7356                ) 
    7357                for c, extra_cols in zip( 
    7358                    self.column_args, proxy_compound_columns 
    7359                ) 
    7360            ) 
    7361        else: 
    7362            columns._populate_separate_keys( 
    7363                c._make_proxy( 
    7364                    fromclause, 
    7365                    primary_key=primary_key, 
    7366                    foreign_keys=foreign_keys, 
    7367                ) 
    7368                for c in self.column_args 
    7369            ) 
    7370 
    7371    def _scalar_type(self) -> Union[TypeEngine[Any], Any]: 
    7372        return self.column_args[0].type 
    7373 
    7374 
    7375TextAsFrom = TextualSelect 
    7376"""Backwards compatibility with the previous name""" 
    7377 
    7378 
    7379class AnnotatedFromClause(Annotated): 
    7380    def _copy_internals( 
    7381        self, 
    7382        _annotations_traversal: bool = False, 
    7383        ind_cols_on_fromclause: bool = False, 
    7384        **kw: Any, 
    7385    ) -> None: 
    7386        super()._copy_internals(**kw) 
    7387 
    7388        # passed from annotations._shallow_annotate(), _deep_annotate(), etc. 
    7389        # the traversals used by annotations for these cases are not currently 
    7390        # designed around expecting that inner elements inside of 
    7391        # AnnotatedFromClause's element are also deep copied, so skip for these 
    7392        # cases. in other cases such as plain visitors.cloned_traverse(), we 
    7393        # expect this to happen. see issue #12915 
    7394        if not _annotations_traversal: 
    7395            ee = self._Annotated__element  # type: ignore 
    7396            ee._copy_internals(**kw) 
    7397 
    7398        if ind_cols_on_fromclause: 
    7399            # passed from annotations._deep_annotate().  See that function 
    7400            # for notes 
    7401            ee = self._Annotated__element  # type: ignore 
    7402            self.c = ee.__class__.c.fget(self)  # type: ignore 
    7403 
    7404    @util.ro_memoized_property 
    7405    def c(self) -> ReadOnlyColumnCollection[str, KeyedColumnElement[Any]]: 
    7406        """proxy the .c collection of the underlying FromClause. 
    7407 
    7408        Originally implemented in 2008 as a simple load of the .c collection 
    7409        when the annotated construct was created (see d3621ae961a), in modern 
    7410        SQLAlchemy versions this can be expensive for statements constructed 
    7411        with ORM aliases.   So for #8796 SQLAlchemy 2.0 we instead proxy 
    7412        it, which works just as well. 
    7413 
    7414        Two different use cases seem to require the collection either copied 
    7415        from the underlying one, or unique to this AnnotatedFromClause. 
    7416 
    7417        See test_selectable->test_annotated_corresponding_column 
    7418 
    7419        """ 
    7420        ee = self._Annotated__element  # type: ignore 
    7421        return ee.c  # type: ignore