1# sql/elements.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# mypy: allow-untyped-defs, allow-untyped-calls 
    8 
    9"""Core SQL expression elements, including :class:`_expression.ClauseElement`, 
    10:class:`_expression.ColumnElement`, and derived classes. 
    11 
    12""" 
    13 
    14from __future__ import annotations 
    15 
    16from decimal import Decimal 
    17from enum import Enum 
    18import itertools 
    19import operator 
    20import re 
    21import typing 
    22from typing import AbstractSet 
    23from typing import Any 
    24from typing import Callable 
    25from typing import cast 
    26from typing import Dict 
    27from typing import FrozenSet 
    28from typing import Generic 
    29from typing import Iterable 
    30from typing import Iterator 
    31from typing import List 
    32from typing import Literal 
    33from typing import Mapping 
    34from typing import Optional 
    35from typing import overload 
    36from typing import ParamSpec 
    37from typing import Sequence 
    38from typing import Set 
    39from typing import Tuple as typing_Tuple 
    40from typing import Type 
    41from typing import TYPE_CHECKING 
    42from typing import TypeVar 
    43from typing import Union 
    44 
    45from . import coercions 
    46from . import operators 
    47from . import roles 
    48from . import traversals 
    49from . import type_api 
    50from ._typing import has_schema_attr 
    51from ._typing import is_named_from_clause 
    52from ._typing import is_quoted_name 
    53from ._typing import is_tuple_type 
    54from .annotation import Annotated 
    55from .annotation import SupportsWrappingAnnotations 
    56from .base import _clone 
    57from .base import _expand_cloned 
    58from .base import _generative 
    59from .base import _NoArg 
    60from .base import Executable 
    61from .base import Generative 
    62from .base import HasMemoized 
    63from .base import Immutable 
    64from .base import NO_ARG 
    65from .base import SingletonConstant 
    66from .cache_key import MemoizedHasCacheKey 
    67from .cache_key import NO_CACHE 
    68from .coercions import _document_text_coercion  # noqa 
    69from .operators import ColumnOperators 
    70from .operators import OperatorClass 
    71from .traversals import HasCopyInternals 
    72from .visitors import cloned_traverse 
    73from .visitors import ExternallyTraversible 
    74from .visitors import InternalTraversal 
    75from .visitors import traverse 
    76from .visitors import Visitable 
    77from .. import exc 
    78from .. import inspection 
    79from .. import util 
    80from ..util import HasMemoized_ro_memoized_attribute 
    81from ..util import TypingOnly 
    82from ..util.typing import Self 
    83from ..util.typing import TupleAny 
    84from ..util.typing import Unpack 
    85 
    86 
    87if typing.TYPE_CHECKING: 
    88    from ._typing import _ByArgument 
    89    from ._typing import _ColumnExpressionArgument 
    90    from ._typing import _ColumnExpressionOrStrLabelArgument 
    91    from ._typing import _DMLOnlyColumnArgument 
    92    from ._typing import _HasDialect 
    93    from ._typing import _InfoType 
    94    from ._typing import _PropagateAttrsType 
    95    from ._typing import _TypeEngineArgument 
    96    from .base import _EntityNamespace 
    97    from .base import ColumnSet 
    98    from .cache_key import _CacheKeyTraversalType 
    99    from .cache_key import CacheKey 
    100    from .compiler import Compiled 
    101    from .compiler import SQLCompiler 
    102    from .functions import FunctionElement 
    103    from .operators import OperatorType 
    104    from .schema import Column 
    105    from .schema import DefaultGenerator 
    106    from .schema import FetchedValue 
    107    from .schema import ForeignKey 
    108    from .selectable import _SelectIterable 
    109    from .selectable import FromClause 
    110    from .selectable import NamedFromClause 
    111    from .selectable import TextualSelect 
    112    from .sqltypes import TupleType 
    113    from .type_api import TypeEngine 
    114    from .visitors import _CloneCallableType 
    115    from .visitors import _TraverseInternalsType 
    116    from .visitors import anon_map 
    117    from ..engine import Connection 
    118    from ..engine import Dialect 
    119    from ..engine.interfaces import _CoreMultiExecuteParams 
    120    from ..engine.interfaces import CacheStats 
    121    from ..engine.interfaces import CompiledCacheType 
    122    from ..engine.interfaces import CoreExecuteOptionsParameter 
    123    from ..engine.interfaces import SchemaTranslateMapType 
    124    from ..engine.result import Result 
    125 
    126 
    127_NUMERIC = Union[float, Decimal] 
    128_NUMBER = Union[float, int, Decimal] 
    129 
    130_T = TypeVar("_T", bound="Any") 
    131_T_co = TypeVar("_T_co", bound=Any, covariant=True) 
    132_OPT = TypeVar("_OPT", bound="Any") 
    133_NT = TypeVar("_NT", bound="_NUMERIC") 
    134 
    135_NMT = TypeVar("_NMT", bound="_NUMBER") 
    136 
    137 
    138@overload 
    139def literal( 
    140    value: Any, 
    141    type_: _TypeEngineArgument[_T], 
    142    literal_execute: bool = False, 
    143) -> BindParameter[_T]: ... 
    144 
    145 
    146@overload 
    147def literal( 
    148    value: _T, 
    149    type_: None = None, 
    150    literal_execute: bool = False, 
    151) -> BindParameter[_T]: ... 
    152 
    153 
    154@overload 
    155def literal( 
    156    value: Any, 
    157    type_: Optional[_TypeEngineArgument[Any]] = None, 
    158    literal_execute: bool = False, 
    159) -> BindParameter[Any]: ... 
    160 
    161 
    162def literal( 
    163    value: Any, 
    164    type_: Optional[_TypeEngineArgument[Any]] = None, 
    165    literal_execute: bool = False, 
    166) -> BindParameter[Any]: 
    167    r"""Return a literal clause, bound to a bind parameter. 
    168 
    169    Literal clauses are created automatically when non- 
    170    :class:`_expression.ClauseElement` objects (such as strings, ints, dates, 
    171    etc.) are 
    172    used in a comparison operation with a :class:`_expression.ColumnElement` 
    173    subclass, 
    174    such as a :class:`~sqlalchemy.schema.Column` object.  Use this function 
    175    to force the generation of a literal clause, which will be created as a 
    176    :class:`BindParameter` with a bound value. 
    177 
    178    :param value: the value to be bound. Can be any Python object supported by 
    179     the underlying DB-API, or is translatable via the given type argument. 
    180 
    181    :param type\_: an optional :class:`~sqlalchemy.types.TypeEngine` which will 
    182     provide bind-parameter translation for this literal. 
    183 
    184    :param literal_execute: optional bool, when True, the SQL engine will 
    185     attempt to render the bound value directly in the SQL statement at 
    186     execution time rather than providing as a parameter value. 
    187 
    188     .. versionadded:: 2.0 
    189 
    190    """ 
    191    return coercions.expect( 
    192        roles.LiteralValueRole, 
    193        value, 
    194        type_=type_, 
    195        literal_execute=literal_execute, 
    196    ) 
    197 
    198 
    199def literal_column( 
    200    text: str, type_: Optional[_TypeEngineArgument[_T]] = None 
    201) -> ColumnClause[_T]: 
    202    r"""Produce a :class:`.ColumnClause` object that has the 
    203    :paramref:`_expression.column.is_literal` flag set to True. 
    204 
    205    :func:`_expression.literal_column` is similar to 
    206    :func:`_expression.column`, except that 
    207    it is more often used as a "standalone" column expression that renders 
    208    exactly as stated; while :func:`_expression.column` 
    209    stores a string name that 
    210    will be assumed to be part of a table and may be quoted as such, 
    211    :func:`_expression.literal_column` can be that, 
    212    or any other arbitrary column-oriented 
    213    expression. 
    214 
    215    :param text: the text of the expression; can be any SQL expression. 
    216      Quoting rules will not be applied. To specify a column-name expression 
    217      which should be subject to quoting rules, use the :func:`column` 
    218      function. 
    219 
    220    :param type\_: an optional :class:`~sqlalchemy.types.TypeEngine` 
    221      object which will 
    222      provide result-set translation and additional expression semantics for 
    223      this column. If left as ``None`` the type will be :class:`.NullType`. 
    224 
    225    .. seealso:: 
    226 
    227        :func:`_expression.column` 
    228 
    229        :func:`_expression.text` 
    230 
    231        :ref:`tutorial_select_arbitrary_text` 
    232 
    233    """ 
    234    return ColumnClause(text, type_=type_, is_literal=True) 
    235 
    236 
    237class CompilerElement(Visitable): 
    238    """base class for SQL elements that can be compiled to produce a 
    239    SQL string. 
    240 
    241    .. versionadded:: 2.0 
    242 
    243    """ 
    244 
    245    __slots__ = () 
    246    __visit_name__ = "compiler_element" 
    247 
    248    supports_execution = False 
    249 
    250    stringify_dialect = "default" 
    251 
    252    @util.preload_module("sqlalchemy.engine.default") 
    253    @util.preload_module("sqlalchemy.engine.url") 
    254    def compile( 
    255        self, 
    256        bind: Optional[_HasDialect] = None, 
    257        dialect: Optional[Dialect] = None, 
    258        **kw: Any, 
    259    ) -> Compiled: 
    260        """Compile this SQL expression. 
    261 
    262        The return value is a :class:`~.Compiled` object. 
    263        Calling ``str()`` or ``unicode()`` on the returned value will yield a 
    264        string representation of the result. The 
    265        :class:`~.Compiled` object also can return a 
    266        dictionary of bind parameter names and values 
    267        using the ``params`` accessor. 
    268 
    269        :param bind: An :class:`.Connection` or :class:`.Engine` which 
    270           can provide a :class:`.Dialect` in order to generate a 
    271           :class:`.Compiled` object.  If the ``bind`` and 
    272           ``dialect`` parameters are both omitted, a default SQL compiler 
    273           is used. 
    274 
    275        :param column_keys: Used for INSERT and UPDATE statements, a list of 
    276            column names which should be present in the VALUES clause of the 
    277            compiled statement. If ``None``, all columns from the target table 
    278            object are rendered. 
    279 
    280        :param dialect: A :class:`.Dialect` instance which can generate 
    281            a :class:`.Compiled` object.  This argument takes precedence over 
    282            the ``bind`` argument. 
    283 
    284        :param compile_kwargs: optional dictionary of additional parameters 
    285            that will be passed through to the compiler within all "visit" 
    286            methods.  This allows any custom flag to be passed through to 
    287            a custom compilation construct, for example.  It is also used 
    288            for the case of passing the ``literal_binds`` flag through:: 
    289 
    290                from sqlalchemy.sql import table, column, select 
    291 
    292                t = table("t", column("x")) 
    293 
    294                s = select(t).where(t.c.x == 5) 
    295 
    296                print(s.compile(compile_kwargs={"literal_binds": True})) 
    297 
    298        .. seealso:: 
    299 
    300            :ref:`faq_sql_expression_string` 
    301 
    302        """ 
    303 
    304        if dialect is None: 
    305            if bind: 
    306                dialect = bind.dialect 
    307            elif self.stringify_dialect == "default": 
    308                dialect = self._default_dialect() 
    309            else: 
    310                url = util.preloaded.engine_url 
    311                dialect = url.URL.create( 
    312                    self.stringify_dialect 
    313                ).get_dialect()() 
    314 
    315        return self._compiler(dialect, **kw) 
    316 
    317    def _default_dialect(self): 
    318        default = util.preloaded.engine_default 
    319        return default.StrCompileDialect() 
    320 
    321    def _compiler(self, dialect: Dialect, **kw: Any) -> Compiled: 
    322        """Return a compiler appropriate for this ClauseElement, given a 
    323        Dialect.""" 
    324 
    325        if TYPE_CHECKING: 
    326            assert isinstance(self, ClauseElement) 
    327        return dialect.statement_compiler(dialect, self, **kw) 
    328 
    329    def __str__(self) -> str: 
    330        return str(self.compile()) 
    331 
    332 
    333@inspection._self_inspects 
    334class ClauseElement( 
    335    SupportsWrappingAnnotations, 
    336    MemoizedHasCacheKey, 
    337    HasCopyInternals, 
    338    ExternallyTraversible, 
    339    CompilerElement, 
    340): 
    341    """Base class for elements of a programmatically constructed SQL 
    342    expression. 
    343 
    344    """ 
    345 
    346    __visit_name__ = "clause" 
    347 
    348    if TYPE_CHECKING: 
    349 
    350        @util.memoized_property 
    351        def _propagate_attrs(self) -> _PropagateAttrsType: 
    352            """like annotations, however these propagate outwards liberally 
    353            as SQL constructs are built, and are set up at construction time. 
    354 
    355            """ 
    356            ... 
    357 
    358    else: 
    359        _propagate_attrs = util.EMPTY_DICT 
    360 
    361    @util.ro_memoized_property 
    362    def description(self) -> Optional[str]: 
    363        return None 
    364 
    365    _is_clone_of: Optional[Self] = None 
    366 
    367    is_clause_element = True 
    368    is_selectable = False 
    369    is_dml = False 
    370    _is_column_element = False 
    371    _is_keyed_column_element = False 
    372    _is_table = False 
    373    _gen_static_annotations_cache_key = False 
    374    _is_textual = False 
    375    _is_from_clause = False 
    376    _is_returns_rows = False 
    377    _is_text_clause = False 
    378    _is_from_container = False 
    379    _is_select_container = False 
    380    _is_select_base = False 
    381    _is_select_statement = False 
    382    _is_bind_parameter = False 
    383    _is_clause_list = False 
    384    _is_lambda_element = False 
    385    _is_singleton_constant = False 
    386    _is_immutable = False 
    387    _is_star = False 
    388 
    389    @property 
    390    def _order_by_label_element(self) -> Optional[Label[Any]]: 
    391        return None 
    392 
    393    _cache_key_traversal: _CacheKeyTraversalType = None 
    394 
    395    negation_clause: ColumnElement[bool] 
    396 
    397    if typing.TYPE_CHECKING: 
    398 
    399        def get_children( 
    400            self, *, omit_attrs: typing_Tuple[str, ...] = ..., **kw: Any 
    401        ) -> Iterable[ClauseElement]: ... 
    402 
    403    @util.ro_non_memoized_property 
    404    def _from_objects(self) -> List[FromClause]: 
    405        return [] 
    406 
    407    def _set_propagate_attrs(self, values: Mapping[str, Any]) -> Self: 
    408        # usually, self._propagate_attrs is empty here.  one case where it's 
    409        # not is a subquery against ORM select, that is then pulled as a 
    410        # property of an aliased class.   should all be good 
    411 
    412        # assert not self._propagate_attrs 
    413 
    414        self._propagate_attrs = util.immutabledict(values) 
    415        return self 
    416 
    417    def _default_compiler(self) -> SQLCompiler: 
    418        dialect = self._default_dialect() 
    419        return dialect.statement_compiler(dialect, self)  # type: ignore 
    420 
    421    def _clone(self, **kw: Any) -> Self: 
    422        """Create a shallow copy of this ClauseElement. 
    423 
    424        This method may be used by a generative API.  Its also used as 
    425        part of the "deep" copy afforded by a traversal that combines 
    426        the _copy_internals() method. 
    427 
    428        """ 
    429 
    430        skip = self._memoized_keys 
    431        c = self.__class__.__new__(self.__class__) 
    432 
    433        if skip: 
    434            # ensure this iteration remains atomic 
    435            c.__dict__ = { 
    436                k: v for k, v in self.__dict__.copy().items() if k not in skip 
    437            } 
    438        else: 
    439            c.__dict__ = self.__dict__.copy() 
    440 
    441        # this is a marker that helps to "equate" clauses to each other 
    442        # when a Select returns its list of FROM clauses.  the cloning 
    443        # process leaves around a lot of remnants of the previous clause 
    444        # typically in the form of column expressions still attached to the 
    445        # old table. 
    446        cc = self._is_clone_of 
    447        c._is_clone_of = cc if cc is not None else self 
    448        return c 
    449 
    450    def _negate_in_binary(self, negated_op, original_op): 
    451        """a hook to allow the right side of a binary expression to respond 
    452        to a negation of the binary expression. 
    453 
    454        Used for the special case of expanding bind parameter with IN. 
    455 
    456        """ 
    457        return self 
    458 
    459    def _with_binary_element_type(self, type_): 
    460        """in the context of binary expression, convert the type of this 
    461        object to the one given. 
    462 
    463        applies only to :class:`_expression.ColumnElement` classes. 
    464 
    465        """ 
    466        return self 
    467 
    468    @property 
    469    def _constructor(self):  # type: ignore[override] 
    470        """return the 'constructor' for this ClauseElement. 
    471 
    472        This is for the purposes for creating a new object of 
    473        this type.   Usually, its just the element's __class__. 
    474        However, the "Annotated" version of the object overrides 
    475        to return the class of its proxied element. 
    476 
    477        """ 
    478        return self.__class__ 
    479 
    480    @HasMemoized.memoized_attribute 
    481    def _cloned_set(self): 
    482        """Return the set consisting all cloned ancestors of this 
    483        ClauseElement. 
    484 
    485        Includes this ClauseElement.  This accessor tends to be used for 
    486        FromClause objects to identify 'equivalent' FROM clauses, regardless 
    487        of transformative operations. 
    488 
    489        """ 
    490        s = util.column_set() 
    491        f: Optional[ClauseElement] = self 
    492 
    493        # note this creates a cycle, asserted in test_memusage. however, 
    494        # turning this into a plain @property adds tends of thousands of method 
    495        # calls to Core / ORM performance tests, so the small overhead 
    496        # introduced by the relatively small amount of short term cycles 
    497        # produced here is preferable 
    498        while f is not None: 
    499            s.add(f) 
    500            f = f._is_clone_of 
    501        return s 
    502 
    503    def _de_clone(self): 
    504        while self._is_clone_of is not None: 
    505            self = self._is_clone_of 
    506        return self 
    507 
    508    @util.ro_non_memoized_property 
    509    def entity_namespace(self) -> _EntityNamespace: 
    510        raise AttributeError( 
    511            "This SQL expression has no entity namespace " 
    512            "with which to filter from." 
    513        ) 
    514 
    515    def __getstate__(self): 
    516        d = self.__dict__.copy() 
    517        d.pop("_is_clone_of", None) 
    518        d.pop("_generate_cache_key", None) 
    519        return d 
    520 
    521    def _execute_on_connection( 
    522        self, 
    523        connection: Connection, 
    524        distilled_params: _CoreMultiExecuteParams, 
    525        execution_options: CoreExecuteOptionsParameter, 
    526    ) -> Result[Unpack[TupleAny]]: 
    527        if self.supports_execution: 
    528            if TYPE_CHECKING: 
    529                assert isinstance(self, Executable) 
    530            return connection._execute_clauseelement( 
    531                self, distilled_params, execution_options 
    532            ) 
    533        else: 
    534            raise exc.ObjectNotExecutableError(self) 
    535 
    536    def _execute_on_scalar( 
    537        self, 
    538        connection: Connection, 
    539        distilled_params: _CoreMultiExecuteParams, 
    540        execution_options: CoreExecuteOptionsParameter, 
    541    ) -> Any: 
    542        """an additional hook for subclasses to provide a different 
    543        implementation for connection.scalar() vs. connection.execute(). 
    544 
    545        .. versionadded:: 2.0 
    546 
    547        """ 
    548        return self._execute_on_connection( 
    549            connection, distilled_params, execution_options 
    550        ).scalar() 
    551 
    552    def _get_embedded_bindparams(self) -> Sequence[BindParameter[Any]]: 
    553        """Return the list of :class:`.BindParameter` objects embedded in the 
    554        object. 
    555 
    556        This accomplishes the same purpose as ``visitors.traverse()`` or 
    557        similar would provide, however by making use of the cache key 
    558        it takes advantage of memoization of the key to result in fewer 
    559        net method calls, assuming the statement is also going to be 
    560        executed. 
    561 
    562        """ 
    563 
    564        key = self._generate_cache_key() 
    565        if key is None: 
    566            bindparams: List[BindParameter[Any]] = [] 
    567 
    568            traverse(self, {}, {"bindparam": bindparams.append}) 
    569            return bindparams 
    570 
    571        else: 
    572            return key.bindparams 
    573 
    574    def unique_params( 
    575        self, 
    576        __optionaldict: Optional[Dict[str, Any]] = None, 
    577        /, 
    578        **kwargs: Any, 
    579    ) -> Self: 
    580        """Return a copy with :func:`_expression.bindparam` elements 
    581        replaced. 
    582 
    583        Same functionality as :meth:`_expression.ClauseElement.params`, 
    584        except adds `unique=True` 
    585        to affected bind parameters so that multiple statements can be 
    586        used. 
    587 
    588        """ 
    589        return self._replace_params(True, __optionaldict, kwargs) 
    590 
    591    def params( 
    592        self, 
    593        __optionaldict: Optional[Mapping[str, Any]] = None, 
    594        /, 
    595        **kwargs: Any, 
    596    ) -> Self: 
    597        """Return a copy with :func:`_expression.bindparam` elements 
    598        replaced. 
    599 
    600        Returns a copy of this ClauseElement with 
    601        :func:`_expression.bindparam` 
    602        elements replaced with values taken from the given dictionary:: 
    603 
    604          >>> clause = column("x") + bindparam("foo") 
    605          >>> print(clause.compile().params) 
    606          {'foo':None} 
    607          >>> print(clause.params({"foo": 7}).compile().params) 
    608          {'foo':7} 
    609 
    610        """ 
    611        return self._replace_params(False, __optionaldict, kwargs) 
    612 
    613    def _replace_params( 
    614        self, 
    615        unique: bool, 
    616        optionaldict: Optional[Mapping[str, Any]], 
    617        kwargs: Dict[str, Any], 
    618    ) -> Self: 
    619        if optionaldict: 
    620            kwargs.update(optionaldict) 
    621 
    622        def visit_bindparam(bind: BindParameter[Any]) -> None: 
    623            if bind.key in kwargs: 
    624                bind.value = kwargs[bind.key] 
    625                bind.required = False 
    626            if unique: 
    627                bind._convert_to_unique() 
    628 
    629        return cloned_traverse( 
    630            self, 
    631            {"maintain_key": True, "detect_subquery_cols": True}, 
    632            {"bindparam": visit_bindparam}, 
    633        ) 
    634 
    635    def compare(self, other: ClauseElement, **kw: Any) -> bool: 
    636        r"""Compare this :class:`_expression.ClauseElement` to 
    637        the given :class:`_expression.ClauseElement`. 
    638 
    639        Subclasses should override the default behavior, which is a 
    640        straight identity comparison. 
    641 
    642        \**kw are arguments consumed by subclass ``compare()`` methods and 
    643        may be used to modify the criteria for comparison 
    644        (see :class:`_expression.ColumnElement`). 
    645 
    646        """ 
    647        return traversals.compare(self, other, **kw) 
    648 
    649    def self_group( 
    650        self, against: Optional[OperatorType] = None 
    651    ) -> ClauseElement: 
    652        """Apply a 'grouping' to this :class:`_expression.ClauseElement`. 
    653 
    654        This method is overridden by subclasses to return a "grouping" 
    655        construct, i.e. parenthesis.   In particular it's used by "binary" 
    656        expressions to provide a grouping around themselves when placed into a 
    657        larger expression, as well as by :func:`_expression.select` 
    658        constructs when placed into the FROM clause of another 
    659        :func:`_expression.select`.  (Note that subqueries should be 
    660        normally created using the :meth:`_expression.Select.alias` method, 
    661        as many 
    662        platforms require nested SELECT statements to be named). 
    663 
    664        As expressions are composed together, the application of 
    665        :meth:`self_group` is automatic - end-user code should never 
    666        need to use this method directly.  Note that SQLAlchemy's 
    667        clause constructs take operator precedence into account - 
    668        so parenthesis might not be needed, for example, in 
    669        an expression like ``x OR (y AND z)`` - AND takes precedence 
    670        over OR. 
    671 
    672        The base :meth:`self_group` method of 
    673        :class:`_expression.ClauseElement` 
    674        just returns self. 
    675        """ 
    676        return self 
    677 
    678    def _ungroup(self) -> ClauseElement: 
    679        """Return this :class:`_expression.ClauseElement` 
    680        without any groupings. 
    681        """ 
    682 
    683        return self 
    684 
    685    def _compile_w_cache( 
    686        self, 
    687        dialect: Dialect, 
    688        *, 
    689        compiled_cache: Optional[CompiledCacheType], 
    690        column_keys: List[str], 
    691        for_executemany: bool = False, 
    692        schema_translate_map: Optional[SchemaTranslateMapType] = None, 
    693        **kw: Any, 
    694    ) -> typing_Tuple[ 
    695        Compiled, Optional[Sequence[BindParameter[Any]]], CacheStats 
    696    ]: 
    697        elem_cache_key: Optional[CacheKey] 
    698 
    699        if compiled_cache is not None and dialect._supports_statement_cache: 
    700            elem_cache_key = self._generate_cache_key() 
    701        else: 
    702            elem_cache_key = None 
    703 
    704        extracted_params: Optional[Sequence[BindParameter[Any]]] 
    705        if elem_cache_key is not None: 
    706            if TYPE_CHECKING: 
    707                assert compiled_cache is not None 
    708 
    709            cache_key, extracted_params = elem_cache_key 
    710            key = ( 
    711                dialect, 
    712                cache_key, 
    713                tuple(column_keys), 
    714                bool(schema_translate_map), 
    715                for_executemany, 
    716            ) 
    717            compiled_sql = compiled_cache.get(key) 
    718 
    719            if compiled_sql is None: 
    720                cache_hit = dialect.CACHE_MISS 
    721                compiled_sql = self._compiler( 
    722                    dialect, 
    723                    cache_key=elem_cache_key, 
    724                    column_keys=column_keys, 
    725                    for_executemany=for_executemany, 
    726                    schema_translate_map=schema_translate_map, 
    727                    **kw, 
    728                ) 
    729                compiled_cache[key] = compiled_sql 
    730            else: 
    731                cache_hit = dialect.CACHE_HIT 
    732        else: 
    733            extracted_params = None 
    734            compiled_sql = self._compiler( 
    735                dialect, 
    736                cache_key=elem_cache_key, 
    737                column_keys=column_keys, 
    738                for_executemany=for_executemany, 
    739                schema_translate_map=schema_translate_map, 
    740                **kw, 
    741            ) 
    742 
    743            if not dialect._supports_statement_cache: 
    744                cache_hit = dialect.NO_DIALECT_SUPPORT 
    745            elif compiled_cache is None: 
    746                cache_hit = dialect.CACHING_DISABLED 
    747            else: 
    748                cache_hit = dialect.NO_CACHE_KEY 
    749 
    750        return compiled_sql, extracted_params, cache_hit 
    751 
    752    def __invert__(self): 
    753        # undocumented element currently used by the ORM for 
    754        # relationship.contains() 
    755        if hasattr(self, "negation_clause"): 
    756            return self.negation_clause 
    757        else: 
    758            return self._negate() 
    759 
    760    def _negate(self) -> ClauseElement: 
    761        # TODO: this code is uncovered and in all likelihood is not included 
    762        # in any codepath.  So this should raise NotImplementedError in 2.1 
    763        grouped = self.self_group(against=operators.inv) 
    764        assert isinstance(grouped, ColumnElement) 
    765        return UnaryExpression(grouped, operator=operators.inv) 
    766 
    767    def __bool__(self): 
    768        raise TypeError("Boolean value of this clause is not defined") 
    769 
    770    def __repr__(self): 
    771        friendly = self.description 
    772        if friendly is None: 
    773            return object.__repr__(self) 
    774        else: 
    775            return "<%s.%s at 0x%x; %s>" % ( 
    776                self.__module__, 
    777                self.__class__.__name__, 
    778                id(self), 
    779                friendly, 
    780            ) 
    781 
    782 
    783class DQLDMLClauseElement(ClauseElement): 
    784    """represents a :class:`.ClauseElement` that compiles to a DQL or DML 
    785    expression, not DDL. 
    786 
    787    .. versionadded:: 2.0 
    788 
    789    """ 
    790 
    791    if typing.TYPE_CHECKING: 
    792 
    793        def _compiler(self, dialect: Dialect, **kw: Any) -> SQLCompiler: 
    794            """Return a compiler appropriate for this ClauseElement, given a 
    795            Dialect.""" 
    796            ... 
    797 
    798        def compile(  # noqa: A001 
    799            self, 
    800            bind: Optional[_HasDialect] = None, 
    801            dialect: Optional[Dialect] = None, 
    802            **kw: Any, 
    803        ) -> SQLCompiler: ... 
    804 
    805 
    806class CompilerColumnElement( 
    807    roles.DMLColumnRole, 
    808    roles.DDLConstraintColumnRole, 
    809    roles.ColumnsClauseRole, 
    810    CompilerElement, 
    811): 
    812    """A compiler-only column element used for ad-hoc string compilations. 
    813 
    814    .. versionadded:: 2.0 
    815 
    816    """ 
    817 
    818    __slots__ = () 
    819 
    820    _propagate_attrs = util.EMPTY_DICT 
    821    _is_collection_aggregate = False 
    822    _is_implicitly_boolean = False 
    823 
    824    def _with_binary_element_type(self, type_): 
    825        raise NotImplementedError() 
    826 
    827    def _gen_cache_key(self, anon_map, bindparams): 
    828        raise NotImplementedError() 
    829 
    830    @property 
    831    def _from_objects(self) -> List[FromClause]: 
    832        raise NotImplementedError() 
    833 
    834 
    835# SQLCoreOperations should be suiting the ExpressionElementRole 
    836# and ColumnsClauseRole.   however the MRO issues become too elaborate 
    837# at the moment. 
    838class SQLCoreOperations(Generic[_T_co], ColumnOperators, TypingOnly): 
    839    __slots__ = () 
    840 
    841    # annotations for comparison methods 
    842    # these are from operators->Operators / ColumnOperators, 
    843    # redefined with the specific types returned by ColumnElement hierarchies 
    844    if typing.TYPE_CHECKING: 
    845 
    846        @util.non_memoized_property 
    847        def _propagate_attrs(self) -> _PropagateAttrsType: ... 
    848 
    849        def operate( 
    850            self, op: OperatorType, *other: Any, **kwargs: Any 
    851        ) -> ColumnElement[Any]: ... 
    852 
    853        def reverse_operate( 
    854            self, op: OperatorType, other: Any, **kwargs: Any 
    855        ) -> ColumnElement[Any]: ... 
    856 
    857        @overload 
    858        def op( 
    859            self, 
    860            opstring: str, 
    861            precedence: int = ..., 
    862            is_comparison: bool = ..., 
    863            *, 
    864            return_type: _TypeEngineArgument[_OPT], 
    865            python_impl: Optional[Callable[..., Any]] = None, 
    866            operator_class: OperatorClass = ..., 
    867        ) -> Callable[[Any], BinaryExpression[_OPT]]: ... 
    868 
    869        @overload 
    870        def op( 
    871            self, 
    872            opstring: str, 
    873            precedence: int = ..., 
    874            is_comparison: bool = ..., 
    875            return_type: Optional[_TypeEngineArgument[Any]] = ..., 
    876            python_impl: Optional[Callable[..., Any]] = ..., 
    877            operator_class: OperatorClass = ..., 
    878        ) -> Callable[[Any], BinaryExpression[Any]]: ... 
    879 
    880        def op( 
    881            self, 
    882            opstring: str, 
    883            precedence: int = 0, 
    884            is_comparison: bool = False, 
    885            return_type: Optional[_TypeEngineArgument[Any]] = None, 
    886            python_impl: Optional[Callable[..., Any]] = None, 
    887            operator_class: OperatorClass = OperatorClass.BASE, 
    888        ) -> Callable[[Any], BinaryExpression[Any]]: ... 
    889 
    890        def bool_op( 
    891            self, 
    892            opstring: str, 
    893            precedence: int = 0, 
    894            python_impl: Optional[Callable[..., Any]] = None, 
    895        ) -> Callable[[Any], BinaryExpression[bool]]: ... 
    896 
    897        def __and__(self, other: Any) -> BooleanClauseList: ... 
    898 
    899        def __or__(self, other: Any) -> BooleanClauseList: ... 
    900 
    901        def __invert__(self) -> ColumnElement[_T_co]: ... 
    902 
    903        def __lt__(self, other: Any) -> ColumnElement[bool]: ... 
    904 
    905        def __le__(self, other: Any) -> ColumnElement[bool]: ... 
    906 
    907        # declare also that this class has an hash method otherwise 
    908        # it may be assumed to be None by type checkers since the 
    909        # object defines __eq__ and python sets it to None in that case: 
    910        # https://docs.python.org/3/reference/datamodel.html#object.__hash__ 
    911        def __hash__(self) -> int: ... 
    912 
    913        def __eq__(self, other: Any) -> ColumnElement[bool]:  # type: ignore[override]  # noqa: E501 
    914            ... 
    915 
    916        def __ne__(self, other: Any) -> ColumnElement[bool]:  # type: ignore[override]  # noqa: E501 
    917            ... 
    918 
    919        def is_distinct_from(self, other: Any) -> ColumnElement[bool]: ... 
    920 
    921        def is_not_distinct_from(self, other: Any) -> ColumnElement[bool]: ... 
    922 
    923        def __gt__(self, other: Any) -> ColumnElement[bool]: ... 
    924 
    925        def __ge__(self, other: Any) -> ColumnElement[bool]: ... 
    926 
    927        def __neg__(self) -> UnaryExpression[_T_co]: ... 
    928 
    929        def __contains__(self, other: Any) -> ColumnElement[bool]: ... 
    930 
    931        def __getitem__(self, index: Any) -> ColumnElement[Any]: ... 
    932 
    933        @overload 
    934        def __lshift__(self: _SQO[int], other: Any) -> ColumnElement[int]: ... 
    935 
    936        @overload 
    937        def __lshift__(self, other: Any) -> ColumnElement[Any]: ... 
    938 
    939        def __lshift__(self, other: Any) -> ColumnElement[Any]: ... 
    940 
    941        @overload 
    942        def __rlshift__(self: _SQO[int], other: Any) -> ColumnElement[int]: ... 
    943 
    944        @overload 
    945        def __rlshift__(self, other: Any) -> ColumnElement[Any]: ... 
    946 
    947        def __rlshift__(self, other: Any) -> ColumnElement[Any]: ... 
    948 
    949        @overload 
    950        def __rshift__(self: _SQO[int], other: Any) -> ColumnElement[int]: ... 
    951 
    952        @overload 
    953        def __rshift__(self, other: Any) -> ColumnElement[Any]: ... 
    954 
    955        def __rshift__(self, other: Any) -> ColumnElement[Any]: ... 
    956 
    957        @overload 
    958        def __rrshift__(self: _SQO[int], other: Any) -> ColumnElement[int]: ... 
    959 
    960        @overload 
    961        def __rrshift__(self, other: Any) -> ColumnElement[Any]: ... 
    962 
    963        def __rrshift__(self, other: Any) -> ColumnElement[Any]: ... 
    964 
    965        def __matmul__(self, other: Any) -> ColumnElement[Any]: ... 
    966 
    967        def __rmatmul__(self, other: Any) -> ColumnElement[Any]: ... 
    968 
    969        @overload 
    970        def concat(self: _SQO[str], other: Any) -> ColumnElement[str]: ... 
    971 
    972        @overload 
    973        def concat(self, other: Any) -> ColumnElement[Any]: ... 
    974 
    975        def concat(self, other: Any) -> ColumnElement[Any]: ... 
    976 
    977        def like( 
    978            self, other: Any, escape: Optional[str] = None 
    979        ) -> BinaryExpression[bool]: ... 
    980 
    981        def ilike( 
    982            self, other: Any, escape: Optional[str] = None 
    983        ) -> BinaryExpression[bool]: ... 
    984 
    985        def bitwise_xor(self, other: Any) -> BinaryExpression[Any]: ... 
    986 
    987        def bitwise_or(self, other: Any) -> BinaryExpression[Any]: ... 
    988 
    989        def bitwise_and(self, other: Any) -> BinaryExpression[Any]: ... 
    990 
    991        def bitwise_not(self) -> UnaryExpression[_T_co]: ... 
    992 
    993        def bitwise_lshift(self, other: Any) -> BinaryExpression[Any]: ... 
    994 
    995        def bitwise_rshift(self, other: Any) -> BinaryExpression[Any]: ... 
    996 
    997        def in_( 
    998            self, 
    999            other: Union[ 
    1000                Iterable[Any], BindParameter[Any], roles.InElementRole 
    1001            ], 
    1002        ) -> BinaryExpression[bool]: ... 
    1003 
    1004        def not_in( 
    1005            self, 
    1006            other: Union[ 
    1007                Iterable[Any], BindParameter[Any], roles.InElementRole 
    1008            ], 
    1009        ) -> BinaryExpression[bool]: ... 
    1010 
    1011        def notin_( 
    1012            self, 
    1013            other: Union[ 
    1014                Iterable[Any], BindParameter[Any], roles.InElementRole 
    1015            ], 
    1016        ) -> BinaryExpression[bool]: ... 
    1017 
    1018        def not_like( 
    1019            self, other: Any, escape: Optional[str] = None 
    1020        ) -> BinaryExpression[bool]: ... 
    1021 
    1022        def notlike( 
    1023            self, other: Any, escape: Optional[str] = None 
    1024        ) -> BinaryExpression[bool]: ... 
    1025 
    1026        def not_ilike( 
    1027            self, other: Any, escape: Optional[str] = None 
    1028        ) -> BinaryExpression[bool]: ... 
    1029 
    1030        def notilike( 
    1031            self, other: Any, escape: Optional[str] = None 
    1032        ) -> BinaryExpression[bool]: ... 
    1033 
    1034        def is_(self, other: Any) -> BinaryExpression[bool]: ... 
    1035 
    1036        def is_not(self, other: Any) -> BinaryExpression[bool]: ... 
    1037 
    1038        def isnot(self, other: Any) -> BinaryExpression[bool]: ... 
    1039 
    1040        def startswith( 
    1041            self, 
    1042            other: Any, 
    1043            escape: Optional[str] = None, 
    1044            autoescape: bool = False, 
    1045        ) -> ColumnElement[bool]: ... 
    1046 
    1047        def istartswith( 
    1048            self, 
    1049            other: Any, 
    1050            escape: Optional[str] = None, 
    1051            autoescape: bool = False, 
    1052        ) -> ColumnElement[bool]: ... 
    1053 
    1054        def endswith( 
    1055            self, 
    1056            other: Any, 
    1057            escape: Optional[str] = None, 
    1058            autoescape: bool = False, 
    1059        ) -> ColumnElement[bool]: ... 
    1060 
    1061        def iendswith( 
    1062            self, 
    1063            other: Any, 
    1064            escape: Optional[str] = None, 
    1065            autoescape: bool = False, 
    1066        ) -> ColumnElement[bool]: ... 
    1067 
    1068        def contains(self, other: Any, **kw: Any) -> ColumnElement[bool]: ... 
    1069 
    1070        def icontains(self, other: Any, **kw: Any) -> ColumnElement[bool]: ... 
    1071 
    1072        def match(self, other: Any, **kwargs: Any) -> ColumnElement[bool]: ... 
    1073 
    1074        def regexp_match( 
    1075            self, pattern: Any, flags: Optional[str] = None 
    1076        ) -> ColumnElement[bool]: ... 
    1077 
    1078        def regexp_replace( 
    1079            self, pattern: Any, replacement: Any, flags: Optional[str] = None 
    1080        ) -> ColumnElement[str]: ... 
    1081 
    1082        def desc(self) -> UnaryExpression[_T_co]: ... 
    1083 
    1084        def asc(self) -> UnaryExpression[_T_co]: ... 
    1085 
    1086        def nulls_first(self) -> UnaryExpression[_T_co]: ... 
    1087 
    1088        def nullsfirst(self) -> UnaryExpression[_T_co]: ... 
    1089 
    1090        def nulls_last(self) -> UnaryExpression[_T_co]: ... 
    1091 
    1092        def nullslast(self) -> UnaryExpression[_T_co]: ... 
    1093 
    1094        def collate(self, collation: str) -> CollationClause: ... 
    1095 
    1096        def between( 
    1097            self, cleft: Any, cright: Any, symmetric: bool = False 
    1098        ) -> BinaryExpression[bool]: ... 
    1099 
    1100        def distinct(self: _SQO[_T_co]) -> UnaryExpression[_T_co]: ... 
    1101 
    1102        def any_(self) -> CollectionAggregate[Any]: ... 
    1103 
    1104        def all_(self) -> CollectionAggregate[Any]: ... 
    1105 
    1106        # numeric overloads.  These need more tweaking 
    1107        # in particular they all need to have a variant for Optiona[_T] 
    1108        # because Optional only applies to the data side, not the expression 
    1109        # side 
    1110 
    1111        @overload 
    1112        def __add__( 
    1113            self: _SQO[_NMT], 
    1114            other: Any, 
    1115        ) -> ColumnElement[_NMT]: ... 
    1116 
    1117        @overload 
    1118        def __add__( 
    1119            self: _SQO[str], 
    1120            other: Any, 
    1121        ) -> ColumnElement[str]: ... 
    1122 
    1123        @overload 
    1124        def __add__(self, other: Any) -> ColumnElement[Any]: ... 
    1125 
    1126        def __add__(self, other: Any) -> ColumnElement[Any]: ... 
    1127 
    1128        @overload 
    1129        def __radd__(self: _SQO[_NMT], other: Any) -> ColumnElement[_NMT]: ... 
    1130 
    1131        @overload 
    1132        def __radd__(self: _SQO[str], other: Any) -> ColumnElement[str]: ... 
    1133 
    1134        def __radd__(self, other: Any) -> ColumnElement[Any]: ... 
    1135 
    1136        @overload 
    1137        def __sub__( 
    1138            self: _SQO[_NMT], 
    1139            other: Any, 
    1140        ) -> ColumnElement[_NMT]: ... 
    1141 
    1142        @overload 
    1143        def __sub__(self, other: Any) -> ColumnElement[Any]: ... 
    1144 
    1145        def __sub__(self, other: Any) -> ColumnElement[Any]: ... 
    1146 
    1147        @overload 
    1148        def __rsub__( 
    1149            self: _SQO[_NMT], 
    1150            other: Any, 
    1151        ) -> ColumnElement[_NMT]: ... 
    1152 
    1153        @overload 
    1154        def __rsub__(self, other: Any) -> ColumnElement[Any]: ... 
    1155 
    1156        def __rsub__(self, other: Any) -> ColumnElement[Any]: ... 
    1157 
    1158        @overload 
    1159        def __mul__( 
    1160            self: _SQO[_NMT], 
    1161            other: Any, 
    1162        ) -> ColumnElement[_NMT]: ... 
    1163 
    1164        @overload 
    1165        def __mul__(self, other: Any) -> ColumnElement[Any]: ... 
    1166 
    1167        def __mul__(self, other: Any) -> ColumnElement[Any]: ... 
    1168 
    1169        @overload 
    1170        def __rmul__( 
    1171            self: _SQO[_NMT], 
    1172            other: Any, 
    1173        ) -> ColumnElement[_NMT]: ... 
    1174 
    1175        @overload 
    1176        def __rmul__(self, other: Any) -> ColumnElement[Any]: ... 
    1177 
    1178        def __rmul__(self, other: Any) -> ColumnElement[Any]: ... 
    1179 
    1180        @overload 
    1181        def __mod__(self: _SQO[_NMT], other: Any) -> ColumnElement[_NMT]: ... 
    1182 
    1183        @overload 
    1184        def __mod__(self, other: Any) -> ColumnElement[Any]: ... 
    1185 
    1186        def __mod__(self, other: Any) -> ColumnElement[Any]: ... 
    1187 
    1188        @overload 
    1189        def __rmod__(self: _SQO[_NMT], other: Any) -> ColumnElement[_NMT]: ... 
    1190 
    1191        @overload 
    1192        def __rmod__(self, other: Any) -> ColumnElement[Any]: ... 
    1193 
    1194        def __rmod__(self, other: Any) -> ColumnElement[Any]: ... 
    1195 
    1196        @overload 
    1197        def __truediv__( 
    1198            self: _SQO[int], other: Any 
    1199        ) -> ColumnElement[_NUMERIC]: ... 
    1200 
    1201        @overload 
    1202        def __truediv__(self: _SQO[_NT], other: Any) -> ColumnElement[_NT]: ... 
    1203 
    1204        @overload 
    1205        def __truediv__(self, other: Any) -> ColumnElement[Any]: ... 
    1206 
    1207        def __truediv__(self, other: Any) -> ColumnElement[Any]: ... 
    1208 
    1209        @overload 
    1210        def __rtruediv__( 
    1211            self: _SQO[_NMT], other: Any 
    1212        ) -> ColumnElement[_NUMERIC]: ... 
    1213 
    1214        @overload 
    1215        def __rtruediv__(self, other: Any) -> ColumnElement[Any]: ... 
    1216 
    1217        def __rtruediv__(self, other: Any) -> ColumnElement[Any]: ... 
    1218 
    1219        @overload 
    1220        def __floordiv__( 
    1221            self: _SQO[_NMT], other: Any 
    1222        ) -> ColumnElement[_NMT]: ... 
    1223 
    1224        @overload 
    1225        def __floordiv__(self, other: Any) -> ColumnElement[Any]: ... 
    1226 
    1227        def __floordiv__(self, other: Any) -> ColumnElement[Any]: ... 
    1228 
    1229        @overload 
    1230        def __rfloordiv__( 
    1231            self: _SQO[_NMT], other: Any 
    1232        ) -> ColumnElement[_NMT]: ... 
    1233 
    1234        @overload 
    1235        def __rfloordiv__(self, other: Any) -> ColumnElement[Any]: ... 
    1236 
    1237        def __rfloordiv__(self, other: Any) -> ColumnElement[Any]: ... 
    1238 
    1239 
    1240class SQLColumnExpression( 
    1241    SQLCoreOperations[_T_co], roles.ExpressionElementRole[_T_co], TypingOnly 
    1242): 
    1243    """A type that may be used to indicate any SQL column element or object 
    1244    that acts in place of one. 
    1245 
    1246    :class:`.SQLColumnExpression` is a base of 
    1247    :class:`.ColumnElement`, as well as within the bases of ORM elements 
    1248    such as :class:`.InstrumentedAttribute`, and may be used in :pep:`484` 
    1249    typing to indicate arguments or return values that should behave 
    1250    as column expressions. 
    1251 
    1252    .. versionadded:: 2.0.0b4 
    1253 
    1254 
    1255    """ 
    1256 
    1257    __slots__ = () 
    1258 
    1259 
    1260_SQO = SQLCoreOperations 
    1261 
    1262 
    1263class ColumnElement( 
    1264    roles.ColumnArgumentOrKeyRole, 
    1265    roles.StatementOptionRole, 
    1266    roles.WhereHavingRole, 
    1267    roles.BinaryElementRole[_T], 
    1268    roles.OrderByRole, 
    1269    roles.ColumnsClauseRole, 
    1270    roles.LimitOffsetRole, 
    1271    roles.DMLColumnRole, 
    1272    roles.DDLConstraintColumnRole, 
    1273    roles.DDLExpressionRole, 
    1274    SQLColumnExpression[_T], 
    1275    DQLDMLClauseElement, 
    1276): 
    1277    """Represent a column-oriented SQL expression suitable for usage in the 
    1278    "columns" clause, WHERE clause etc. of a statement. 
    1279 
    1280    While the most familiar kind of :class:`_expression.ColumnElement` is the 
    1281    :class:`_schema.Column` object, :class:`_expression.ColumnElement` 
    1282    serves as the basis 
    1283    for any unit that may be present in a SQL expression, including 
    1284    the expressions themselves, SQL functions, bound parameters, 
    1285    literal expressions, keywords such as ``NULL``, etc. 
    1286    :class:`_expression.ColumnElement` 
    1287    is the ultimate base class for all such elements. 
    1288 
    1289    A wide variety of SQLAlchemy Core functions work at the SQL expression 
    1290    level, and are intended to accept instances of 
    1291    :class:`_expression.ColumnElement` as 
    1292    arguments.  These functions will typically document that they accept a 
    1293    "SQL expression" as an argument.  What this means in terms of SQLAlchemy 
    1294    usually refers to an input which is either already in the form of a 
    1295    :class:`_expression.ColumnElement` object, 
    1296    or a value which can be **coerced** into 
    1297    one.  The coercion rules followed by most, but not all, SQLAlchemy Core 
    1298    functions with regards to SQL expressions are as follows: 
    1299 
    1300        * a literal Python value, such as a string, integer or floating 
    1301          point value, boolean, datetime, ``Decimal`` object, or virtually 
    1302          any other Python object, will be coerced into a "literal bound 
    1303          value".  This generally means that a :func:`.bindparam` will be 
    1304          produced featuring the given value embedded into the construct; the 
    1305          resulting :class:`.BindParameter` object is an instance of 
    1306          :class:`_expression.ColumnElement`. 
    1307          The Python value will ultimately be sent 
    1308          to the DBAPI at execution time as a parameterized argument to the 
    1309          ``execute()`` or ``executemany()`` methods, after SQLAlchemy 
    1310          type-specific converters (e.g. those provided by any associated 
    1311          :class:`.TypeEngine` objects) are applied to the value. 
    1312 
    1313        * any special object value, typically ORM-level constructs, which 
    1314          feature an accessor called ``__clause_element__()``.  The Core 
    1315          expression system looks for this method when an object of otherwise 
    1316          unknown type is passed to a function that is looking to coerce the 
    1317          argument into a :class:`_expression.ColumnElement` and sometimes a 
    1318          :class:`_expression.SelectBase` expression. 
    1319          It is used within the ORM to 
    1320          convert from ORM-specific objects like mapped classes and 
    1321          mapped attributes into Core expression objects. 
    1322 
    1323        * The Python ``None`` value is typically interpreted as ``NULL``, 
    1324          which in SQLAlchemy Core produces an instance of :func:`.null`. 
    1325 
    1326    A :class:`_expression.ColumnElement` provides the ability to generate new 
    1327    :class:`_expression.ColumnElement` 
    1328    objects using Python expressions.  This means that Python operators 
    1329    such as ``==``, ``!=`` and ``<`` are overloaded to mimic SQL operations, 
    1330    and allow the instantiation of further :class:`_expression.ColumnElement` 
    1331    instances 
    1332    which are composed from other, more fundamental 
    1333    :class:`_expression.ColumnElement` 
    1334    objects.  For example, two :class:`.ColumnClause` objects can be added 
    1335    together with the addition operator ``+`` to produce 
    1336    a :class:`.BinaryExpression`. 
    1337    Both :class:`.ColumnClause` and :class:`.BinaryExpression` are subclasses 
    1338    of :class:`_expression.ColumnElement`: 
    1339 
    1340    .. sourcecode:: pycon+sql 
    1341 
    1342        >>> from sqlalchemy.sql import column 
    1343        >>> column("a") + column("b") 
    1344        <sqlalchemy.sql.expression.BinaryExpression object at 0x101029dd0> 
    1345        >>> print(column("a") + column("b")) 
    1346        {printsql}a + b 
    1347 
    1348    .. seealso:: 
    1349 
    1350        :class:`_schema.Column` 
    1351 
    1352        :func:`_expression.column` 
    1353 
    1354    """ 
    1355 
    1356    __visit_name__ = "column_element" 
    1357 
    1358    primary_key: bool = False 
    1359    _is_clone_of: Optional[ColumnElement[_T]] 
    1360    _is_column_element = True 
    1361    _insert_sentinel: bool = False 
    1362    _omit_from_statements = False 
    1363    _is_collection_aggregate = False 
    1364 
    1365    foreign_keys: AbstractSet[ForeignKey] = frozenset() 
    1366 
    1367    @util.memoized_property 
    1368    def _proxies(self) -> List[ColumnElement[Any]]: 
    1369        return [] 
    1370 
    1371    @util.non_memoized_property 
    1372    def _tq_label(self) -> Optional[str]: 
    1373        """The named label that can be used to target 
    1374        this column in a result set in a "table qualified" context. 
    1375 
    1376        This label is almost always the label used when 
    1377        rendering <expr> AS <label> in a SELECT statement when using 
    1378        the LABEL_STYLE_TABLENAME_PLUS_COL label style, which is what the 
    1379        legacy ORM ``Query`` object uses as well. 
    1380 
    1381        For a regular Column bound to a Table, this is typically the label 
    1382        <tablename>_<columnname>.  For other constructs, different rules 
    1383        may apply, such as anonymized labels and others. 
    1384 
    1385        .. versionchanged:: 1.4.21 renamed from ``._label`` 
    1386 
    1387        """ 
    1388        return None 
    1389 
    1390    key: Optional[str] = None 
    1391    """The 'key' that in some circumstances refers to this object in a 
    1392    Python namespace. 
    1393 
    1394    This typically refers to the "key" of the column as present in the 
    1395    ``.c`` collection of a selectable, e.g. ``sometable.c["somekey"]`` would 
    1396    return a :class:`_schema.Column` with a ``.key`` of "somekey". 
    1397 
    1398    """ 
    1399 
    1400    @HasMemoized.memoized_attribute 
    1401    def _tq_key_label(self) -> Optional[str]: 
    1402        """A label-based version of 'key' that in some circumstances refers 
    1403        to this object in a Python namespace. 
    1404 
    1405 
    1406        _tq_key_label comes into play when a select() statement is constructed 
    1407        with apply_labels(); in this case, all Column objects in the ``.c`` 
    1408        collection are rendered as <tablename>_<columnname> in SQL; this is 
    1409        essentially the value of ._label. But to locate those columns in the 
    1410        ``.c`` collection, the name is along the lines of <tablename>_<key>; 
    1411        that's the typical value of .key_label. 
    1412 
    1413        .. versionchanged:: 1.4.21 renamed from ``._key_label`` 
    1414 
    1415        """ 
    1416        return self._proxy_key 
    1417 
    1418    @property 
    1419    def _key_label(self) -> Optional[str]: 
    1420        """legacy; renamed to _tq_key_label""" 
    1421        return self._tq_key_label 
    1422 
    1423    @property 
    1424    def _label(self) -> Optional[str]: 
    1425        """legacy; renamed to _tq_label""" 
    1426        return self._tq_label 
    1427 
    1428    @property 
    1429    def _non_anon_label(self) -> Optional[str]: 
    1430        """the 'name' that naturally applies this element when rendered in 
    1431        SQL. 
    1432 
    1433        Concretely, this is the "name" of a column or a label in a 
    1434        SELECT statement; ``<columnname>`` and ``<labelname>`` below: 
    1435 
    1436        .. sourcecode:: sql 
    1437 
    1438            SELECT <columnmame> FROM table 
    1439 
    1440            SELECT column AS <labelname> FROM table 
    1441 
    1442        Above, the two names noted will be what's present in the DBAPI 
    1443        ``cursor.description`` as the names. 
    1444 
    1445        If this attribute returns ``None``, it means that the SQL element as 
    1446        written does not have a 100% fully predictable "name" that would appear 
    1447        in the ``cursor.description``. Examples include SQL functions, CAST 
    1448        functions, etc. While such things do return names in 
    1449        ``cursor.description``, they are only predictable on a 
    1450        database-specific basis; e.g. an expression like ``MAX(table.col)`` may 
    1451        appear as the string ``max`` on one database (like PostgreSQL) or may 
    1452        appear as the whole expression ``max(table.col)`` on SQLite. 
    1453 
    1454        The default implementation looks for a ``.name`` attribute on the 
    1455        object, as has been the precedent established in SQLAlchemy for many 
    1456        years.  An exception is made on the ``FunctionElement`` subclass 
    1457        so that the return value is always ``None``. 
    1458 
    1459        .. versionadded:: 1.4.21 
    1460 
    1461 
    1462 
    1463        """ 
    1464        return getattr(self, "name", None) 
    1465 
    1466    _render_label_in_columns_clause = True 
    1467    """A flag used by select._columns_plus_names that helps to determine 
    1468    we are actually going to render in terms of "SELECT <col> AS <label>". 
    1469    This flag can be returned as False for some Column objects that want 
    1470    to be rendered as simple "SELECT <col>"; typically columns that don't have 
    1471    any parent table and are named the same as what the label would be 
    1472    in any case. 
    1473 
    1474    """ 
    1475 
    1476    _allow_label_resolve = True 
    1477    """A flag that can be flipped to prevent a column from being resolvable 
    1478    by string label name. 
    1479 
    1480    The joined eager loader strategy in the ORM uses this, for example. 
    1481 
    1482    """ 
    1483 
    1484    _is_implicitly_boolean = False 
    1485 
    1486    _alt_names: Sequence[str] = () 
    1487 
    1488    if TYPE_CHECKING: 
    1489 
    1490        def _ungroup(self) -> ColumnElement[_T]: ... 
    1491 
    1492    @overload 
    1493    def self_group(self, against: None = None) -> ColumnElement[_T]: ... 
    1494 
    1495    @overload 
    1496    def self_group( 
    1497        self, against: Optional[OperatorType] = None 
    1498    ) -> ColumnElement[Any]: ... 
    1499 
    1500    def self_group( 
    1501        self, against: Optional[OperatorType] = None 
    1502    ) -> ColumnElement[Any]: 
    1503        if ( 
    1504            against in (operators.and_, operators.or_, operators._asbool) 
    1505            and self.type._type_affinity is type_api.BOOLEANTYPE._type_affinity 
    1506        ): 
    1507            return AsBoolean(self, operators.is_true, operators.is_false) 
    1508        elif against in (operators.any_op, operators.all_op): 
    1509            return Grouping(self) 
    1510        else: 
    1511            return self 
    1512 
    1513    @overload 
    1514    def _negate(self: ColumnElement[bool]) -> ColumnElement[bool]: ... 
    1515 
    1516    @overload 
    1517    def _negate(self: ColumnElement[_T]) -> ColumnElement[_T]: ... 
    1518 
    1519    def _negate(self) -> ColumnElement[Any]: 
    1520        if self.type._type_affinity is type_api.BOOLEANTYPE._type_affinity: 
    1521            return AsBoolean(self, operators.is_false, operators.is_true) 
    1522        else: 
    1523            grouped = self.self_group(against=operators.inv) 
    1524            assert isinstance(grouped, ColumnElement) 
    1525            return UnaryExpression( 
    1526                grouped, 
    1527                operator=operators.inv, 
    1528            ) 
    1529 
    1530    type: TypeEngine[_T] 
    1531 
    1532    if not TYPE_CHECKING: 
    1533 
    1534        @util.memoized_property 
    1535        def type(self) -> TypeEngine[_T]:  # noqa: A001 
    1536            # used for delayed setup of 
    1537            # type_api 
    1538            return type_api.NULLTYPE 
    1539 
    1540    @HasMemoized.memoized_attribute 
    1541    def comparator(self) -> TypeEngine.Comparator[_T]: 
    1542        try: 
    1543            comparator_factory = self.type.comparator_factory 
    1544        except AttributeError as err: 
    1545            raise TypeError( 
    1546                "Object %r associated with '.type' attribute " 
    1547                "is not a TypeEngine class or object" % self.type 
    1548            ) from err 
    1549        else: 
    1550            return comparator_factory(self) 
    1551 
    1552    def __setstate__(self, state): 
    1553        self.__dict__.update(state) 
    1554 
    1555    def __getattr__(self, key: str) -> Any: 
    1556        try: 
    1557            return getattr(self.comparator, key) 
    1558        except AttributeError as err: 
    1559            raise AttributeError( 
    1560                "Neither %r object nor %r object has an attribute %r" 
    1561                % ( 
    1562                    type(self).__name__, 
    1563                    type(self.comparator).__name__, 
    1564                    key, 
    1565                ) 
    1566            ) from err 
    1567 
    1568    def operate( 
    1569        self, 
    1570        op: operators.OperatorType, 
    1571        *other: Any, 
    1572        **kwargs: Any, 
    1573    ) -> ColumnElement[Any]: 
    1574        return op(self.comparator, *other, **kwargs)  # type: ignore[no-any-return]  # noqa: E501 
    1575 
    1576    def reverse_operate( 
    1577        self, op: operators.OperatorType, other: Any, **kwargs: Any 
    1578    ) -> ColumnElement[Any]: 
    1579        return op(other, self.comparator, **kwargs)  # type: ignore[no-any-return]  # noqa: E501 
    1580 
    1581    def _bind_param( 
    1582        self, 
    1583        operator: operators.OperatorType, 
    1584        obj: Any, 
    1585        type_: Optional[TypeEngine[_T]] = None, 
    1586        expanding: bool = False, 
    1587    ) -> BindParameter[_T]: 
    1588        return BindParameter( 
    1589            None, 
    1590            obj, 
    1591            _compared_to_operator=operator, 
    1592            type_=type_, 
    1593            _compared_to_type=self.type, 
    1594            unique=True, 
    1595            expanding=expanding, 
    1596        ) 
    1597 
    1598    @property 
    1599    def expression(self) -> ColumnElement[Any]: 
    1600        """Return a column expression. 
    1601 
    1602        Part of the inspection interface; returns self. 
    1603 
    1604        """ 
    1605        return self 
    1606 
    1607    @property 
    1608    def _select_iterable(self) -> _SelectIterable: 
    1609        return (self,) 
    1610 
    1611    @util.memoized_property 
    1612    def base_columns(self) -> FrozenSet[ColumnElement[Any]]: 
    1613        return frozenset(c for c in self.proxy_set if not c._proxies) 
    1614 
    1615    @util.memoized_property 
    1616    def proxy_set(self) -> FrozenSet[ColumnElement[Any]]: 
    1617        """set of all columns we are proxying 
    1618 
    1619        as of 2.0 this is explicitly deannotated columns.  previously it was 
    1620        effectively deannotated columns but wasn't enforced.  annotated 
    1621        columns should basically not go into sets if at all possible because 
    1622        their hashing behavior is very non-performant. 
    1623 
    1624        """ 
    1625        return frozenset([self._deannotate()]).union( 
    1626            itertools.chain(*[c.proxy_set for c in self._proxies]) 
    1627        ) 
    1628 
    1629    @util.memoized_property 
    1630    def _expanded_proxy_set(self) -> FrozenSet[ColumnElement[Any]]: 
    1631        return frozenset(_expand_cloned(self.proxy_set)) 
    1632 
    1633    def _uncached_proxy_list(self) -> List[ColumnElement[Any]]: 
    1634        """An 'uncached' version of proxy set. 
    1635 
    1636        This list includes annotated columns which perform very poorly in 
    1637        set operations. 
    1638 
    1639        """ 
    1640 
    1641        return [self] + list( 
    1642            itertools.chain(*[c._uncached_proxy_list() for c in self._proxies]) 
    1643        ) 
    1644 
    1645    def shares_lineage(self, othercolumn: ColumnElement[Any]) -> bool: 
    1646        """Return True if the given :class:`_expression.ColumnElement` 
    1647        has a common ancestor to this :class:`_expression.ColumnElement`.""" 
    1648 
    1649        return bool(self.proxy_set.intersection(othercolumn.proxy_set)) 
    1650 
    1651    def _compare_name_for_result(self, other: ColumnElement[Any]) -> bool: 
    1652        """Return True if the given column element compares to this one 
    1653        when targeting within a result row.""" 
    1654 
    1655        return ( 
    1656            hasattr(other, "name") 
    1657            and hasattr(self, "name") 
    1658            and other.name == self.name 
    1659        ) 
    1660 
    1661    @HasMemoized.memoized_attribute 
    1662    def _proxy_key(self) -> Optional[str]: 
    1663        if self._annotations and "proxy_key" in self._annotations: 
    1664            return cast(str, self._annotations["proxy_key"]) 
    1665 
    1666        name = self.key 
    1667        if not name: 
    1668            # there's a bit of a seeming contradiction which is that the 
    1669            # "_non_anon_label" of a column can in fact be an 
    1670            # "_anonymous_label"; this is when it's on a column that is 
    1671            # proxying for an anonymous expression in a subquery. 
    1672            name = self._non_anon_label 
    1673 
    1674        if isinstance(name, _anonymous_label): 
    1675            return None 
    1676        else: 
    1677            return name 
    1678 
    1679    @HasMemoized.memoized_attribute 
    1680    def _expression_label(self) -> Optional[str]: 
    1681        """a suggested label to use in the case that the column has no name, 
    1682        which should be used if possible as the explicit 'AS <label>' 
    1683        where this expression would normally have an anon label. 
    1684 
    1685        this is essentially mostly what _proxy_key does except it returns 
    1686        None if the column has a normal name that can be used. 
    1687 
    1688        """ 
    1689 
    1690        if getattr(self, "name", None) is not None: 
    1691            return None 
    1692        elif self._annotations and "proxy_key" in self._annotations: 
    1693            return cast(str, self._annotations["proxy_key"]) 
    1694        else: 
    1695            return None 
    1696 
    1697    def _make_proxy( 
    1698        self, 
    1699        selectable: FromClause, 
    1700        *, 
    1701        primary_key: ColumnSet, 
    1702        foreign_keys: Set[KeyedColumnElement[Any]], 
    1703        name: Optional[str] = None, 
    1704        key: Optional[str] = None, 
    1705        name_is_truncatable: bool = False, 
    1706        compound_select_cols: Optional[Sequence[ColumnElement[Any]]] = None, 
    1707        **kw: Any, 
    1708    ) -> typing_Tuple[str, ColumnClause[_T]]: 
    1709        """Create a new :class:`_expression.ColumnElement` representing this 
    1710        :class:`_expression.ColumnElement` as it appears in the select list of 
    1711        a descending selectable. 
    1712 
    1713        """ 
    1714        if name is None: 
    1715            name = self._anon_name_label 
    1716            if key is None: 
    1717                key = self._proxy_key 
    1718        else: 
    1719            key = name 
    1720 
    1721        assert key is not None 
    1722 
    1723        co: ColumnClause[_T] = ColumnClause( 
    1724            ( 
    1725                coercions.expect(roles.TruncatedLabelRole, name) 
    1726                if name_is_truncatable 
    1727                else name 
    1728            ), 
    1729            type_=getattr(self, "type", None), 
    1730            _selectable=selectable, 
    1731        ) 
    1732 
    1733        co._propagate_attrs = selectable._propagate_attrs 
    1734        if compound_select_cols: 
    1735            co._proxies = list(compound_select_cols) 
    1736        else: 
    1737            co._proxies = [self] 
    1738        if selectable._is_clone_of is not None: 
    1739            co._is_clone_of = selectable._is_clone_of.columns.get(key) 
    1740        return key, co 
    1741 
    1742    def cast(self, type_: _TypeEngineArgument[_OPT]) -> Cast[_OPT]: 
    1743        """Produce a type cast, i.e. ``CAST(<expression> AS <type>)``. 
    1744 
    1745        This is a shortcut to the :func:`_expression.cast` function. 
    1746 
    1747        .. seealso:: 
    1748 
    1749            :ref:`tutorial_casts` 
    1750 
    1751            :func:`_expression.cast` 
    1752 
    1753            :func:`_expression.type_coerce` 
    1754 
    1755        """ 
    1756        return Cast(self, type_) 
    1757 
    1758    def label(self, name: Optional[str]) -> Label[_T]: 
    1759        """Produce a column label, i.e. ``<columnname> AS <name>``. 
    1760 
    1761        This is a shortcut to the :func:`_expression.label` function. 
    1762 
    1763        If 'name' is ``None``, an anonymous label name will be generated. 
    1764 
    1765        """ 
    1766        return Label(name, self, self.type) 
    1767 
    1768    def _anon_label( 
    1769        self, seed: Optional[str], add_hash: Optional[int] = None 
    1770    ) -> _anonymous_label: 
    1771        while self._is_clone_of is not None: 
    1772            self = self._is_clone_of 
    1773 
    1774        # as of 1.4 anonymous label for ColumnElement uses hash(), not id(), 
    1775        # as the identifier, because a column and its annotated version are 
    1776        # the same thing in a SQL statement 
    1777        hash_value = hash(self) 
    1778 
    1779        if add_hash: 
    1780            # this path is used for disambiguating anon labels that would 
    1781            # otherwise be the same name for the same element repeated. 
    1782            # an additional numeric value is factored in for each label. 
    1783 
    1784            # shift hash(self) (which is id(self), typically 8 byte integer) 
    1785            # 16 bits leftward.  fill extra add_hash on right 
    1786            assert add_hash < (2 << 15) 
    1787            assert seed 
    1788            hash_value = (hash_value << 16) | add_hash 
    1789 
    1790            # extra underscore is added for labels with extra hash 
    1791            # values, to isolate the "deduped anon" namespace from the 
    1792            # regular namespace.  eliminates chance of these 
    1793            # manufactured hash values overlapping with regular ones for some 
    1794            # undefined python interpreter 
    1795            seed = seed + "_" 
    1796 
    1797        if isinstance(seed, _anonymous_label): 
    1798            # NOTE: the space after the hash is required 
    1799            return _anonymous_label(f"{seed}%({hash_value} )s") 
    1800 
    1801        return _anonymous_label.safe_construct(hash_value, seed or "anon") 
    1802 
    1803    @util.memoized_property 
    1804    def _anon_name_label(self) -> str: 
    1805        """Provides a constant 'anonymous label' for this ColumnElement. 
    1806 
    1807        This is a label() expression which will be named at compile time. 
    1808        The same label() is returned each time ``anon_label`` is called so 
    1809        that expressions can reference ``anon_label`` multiple times, 
    1810        producing the same label name at compile time. 
    1811 
    1812        The compiler uses this function automatically at compile time 
    1813        for expressions that are known to be 'unnamed' like binary 
    1814        expressions and function calls. 
    1815 
    1816        .. versionchanged:: 1.4.9 - this attribute was not intended to be 
    1817           public and is renamed to _anon_name_label.  anon_name exists 
    1818           for backwards compat 
    1819 
    1820        """ 
    1821        name = getattr(self, "name", None) 
    1822        return self._anon_label(name) 
    1823 
    1824    @util.memoized_property 
    1825    def _anon_key_label(self) -> _anonymous_label: 
    1826        """Provides a constant 'anonymous key label' for this ColumnElement. 
    1827 
    1828        Compare to ``anon_label``, except that the "key" of the column, 
    1829        if available, is used to generate the label. 
    1830 
    1831        This is used when a deduplicating key is placed into the columns 
    1832        collection of a selectable. 
    1833 
    1834        .. versionchanged:: 1.4.9 - this attribute was not intended to be 
    1835           public and is renamed to _anon_key_label.  anon_key_label exists 
    1836           for backwards compat 
    1837 
    1838        """ 
    1839        return self._anon_label(self._proxy_key) 
    1840 
    1841    @property 
    1842    @util.deprecated( 
    1843        "1.4", 
    1844        "The :attr:`_expression.ColumnElement.anon_label` attribute is now " 
    1845        "private, and the public accessor is deprecated.", 
    1846    ) 
    1847    def anon_label(self) -> str: 
    1848        return self._anon_name_label 
    1849 
    1850    @property 
    1851    @util.deprecated( 
    1852        "1.4", 
    1853        "The :attr:`_expression.ColumnElement.anon_key_label` attribute is " 
    1854        "now private, and the public accessor is deprecated.", 
    1855    ) 
    1856    def anon_key_label(self) -> str: 
    1857        return self._anon_key_label 
    1858 
    1859    def _dedupe_anon_label_idx(self, idx: int) -> str: 
    1860        """label to apply to a column that is anon labeled, but repeated 
    1861        in the SELECT, so that we have to make an "extra anon" label that 
    1862        disambiguates it from the previous appearance. 
    1863 
    1864        these labels come out like "foo_bar_id__1" and have double underscores 
    1865        in them. 
    1866 
    1867        """ 
    1868        label = getattr(self, "name", None) 
    1869 
    1870        # current convention is that if the element doesn't have a 
    1871        # ".name" (usually because it is not NamedColumn), we try to 
    1872        # use a "table qualified" form for the "dedupe anon" label, 
    1873        # based on the notion that a label like 
    1874        # "CAST(casttest.v1 AS DECIMAL) AS casttest_v1__1" looks better than 
    1875        # "CAST(casttest.v1 AS DECIMAL) AS anon__1" 
    1876 
    1877        if label is None: 
    1878            return self._dedupe_anon_tq_label_idx(idx) 
    1879        else: 
    1880            return self._anon_label(label, add_hash=idx) 
    1881 
    1882    @util.memoized_property 
    1883    def _anon_tq_label(self) -> _anonymous_label: 
    1884        return self._anon_label(getattr(self, "_tq_label", None)) 
    1885 
    1886    @util.memoized_property 
    1887    def _anon_tq_key_label(self) -> _anonymous_label: 
    1888        return self._anon_label(getattr(self, "_tq_key_label", None)) 
    1889 
    1890    def _dedupe_anon_tq_label_idx(self, idx: int) -> _anonymous_label: 
    1891        label = getattr(self, "_tq_label", None) or "anon" 
    1892 
    1893        return self._anon_label(label, add_hash=idx) 
    1894 
    1895 
    1896class KeyedColumnElement(ColumnElement[_T]): 
    1897    """ColumnElement where ``.key`` is non-None.""" 
    1898 
    1899    _is_keyed_column_element = True 
    1900 
    1901    key: str 
    1902 
    1903 
    1904class WrapsColumnExpression(ColumnElement[_T]): 
    1905    """Mixin that defines a :class:`_expression.ColumnElement` 
    1906    as a wrapper with special 
    1907    labeling behavior for an expression that already has a name. 
    1908 
    1909    .. versionadded:: 1.4 
    1910 
    1911    .. seealso:: 
    1912 
    1913        :ref:`change_4449` 
    1914 
    1915 
    1916    """ 
    1917 
    1918    @property 
    1919    def wrapped_column_expression(self) -> ColumnElement[_T]: 
    1920        raise NotImplementedError() 
    1921 
    1922    @util.non_memoized_property 
    1923    def _tq_label(self) -> Optional[str]: 
    1924        wce = self.wrapped_column_expression 
    1925        if hasattr(wce, "_tq_label"): 
    1926            return wce._tq_label 
    1927        else: 
    1928            return None 
    1929 
    1930    @property 
    1931    def _label(self) -> Optional[str]: 
    1932        return self._tq_label 
    1933 
    1934    @property 
    1935    def _non_anon_label(self) -> Optional[str]: 
    1936        return None 
    1937 
    1938    @util.non_memoized_property 
    1939    def _anon_name_label(self) -> str: 
    1940        wce = self.wrapped_column_expression 
    1941 
    1942        # this logic tries to get the WrappedColumnExpression to render 
    1943        # with "<expr> AS <name>", where "<name>" is the natural name 
    1944        # within the expression itself.   e.g. "CAST(table.foo) AS foo". 
    1945        if not wce._is_text_clause: 
    1946            nal = wce._non_anon_label 
    1947            if nal: 
    1948                return nal 
    1949            elif hasattr(wce, "_anon_name_label"): 
    1950                return wce._anon_name_label 
    1951        return super()._anon_name_label 
    1952 
    1953    def _dedupe_anon_label_idx(self, idx: int) -> str: 
    1954        wce = self.wrapped_column_expression 
    1955        nal = wce._non_anon_label 
    1956        if nal: 
    1957            return self._anon_label(nal + "_") 
    1958        else: 
    1959            return self._dedupe_anon_tq_label_idx(idx) 
    1960 
    1961    @property 
    1962    def _proxy_key(self): 
    1963        wce = self.wrapped_column_expression 
    1964 
    1965        if not wce._is_text_clause: 
    1966            return wce._proxy_key 
    1967        return super()._proxy_key 
    1968 
    1969 
    1970class DMLTargetCopy(roles.InElementRole, KeyedColumnElement[_T]): 
    1971    """Refer to another column's VALUES or SET expression in an INSERT or 
    1972    UPDATE statement. 
    1973 
    1974    See the public-facing :func:`_sql.from_dml_column` constructor for 
    1975    background. 
    1976 
    1977    .. versionadded:: 2.1 
    1978 
    1979 
    1980    """ 
    1981 
    1982    def __init__(self, column: _DMLOnlyColumnArgument[_T]): 
    1983        self.column = coercions.expect(roles.ColumnArgumentRole, column) 
    1984        self.type = self.column.type 
    1985 
    1986    __visit_name__ = "dmltargetcopy" 
    1987 
    1988    _traverse_internals: _TraverseInternalsType = [ 
    1989        ("column", InternalTraversal.dp_clauseelement), 
    1990    ] 
    1991 
    1992 
    1993class BindParameter(roles.InElementRole, KeyedColumnElement[_T]): 
    1994    r"""Represent a "bound expression". 
    1995 
    1996    :class:`.BindParameter` is invoked explicitly using the 
    1997    :func:`.bindparam` function, as in:: 
    1998 
    1999        from sqlalchemy import bindparam 
    2000 
    2001        stmt = select(users_table).where( 
    2002            users_table.c.name == bindparam("username") 
    2003        ) 
    2004 
    2005    Detailed discussion of how :class:`.BindParameter` is used is 
    2006    at :func:`.bindparam`. 
    2007 
    2008    .. seealso:: 
    2009 
    2010        :func:`.bindparam` 
    2011 
    2012    """ 
    2013 
    2014    __visit_name__ = "bindparam" 
    2015 
    2016    _traverse_internals: _TraverseInternalsType = [ 
    2017        ("key", InternalTraversal.dp_anon_name), 
    2018        ("type", InternalTraversal.dp_type), 
    2019        ("callable", InternalTraversal.dp_plain_dict), 
    2020        ("value", InternalTraversal.dp_plain_obj), 
    2021        ("literal_execute", InternalTraversal.dp_boolean), 
    2022    ] 
    2023 
    2024    key: str 
    2025    _anon_map_key: Optional[str] = None 
    2026    type: TypeEngine[_T] 
    2027    value: Optional[_T] 
    2028 
    2029    _is_crud = False 
    2030    _is_bind_parameter = True 
    2031 
    2032    # bindparam implements its own _gen_cache_key() method however 
    2033    # we check subclasses for this flag, else no cache key is generated 
    2034    inherit_cache = True 
    2035 
    2036    def __init__( 
    2037        self, 
    2038        key: Optional[str], 
    2039        value: Any = _NoArg.NO_ARG, 
    2040        type_: Optional[_TypeEngineArgument[_T]] = None, 
    2041        unique: bool = False, 
    2042        required: Union[bool, Literal[_NoArg.NO_ARG]] = _NoArg.NO_ARG, 
    2043        quote: Optional[bool] = None, 
    2044        callable_: Optional[Callable[[], Any]] = None, 
    2045        expanding: bool = False, 
    2046        isoutparam: bool = False, 
    2047        literal_execute: bool = False, 
    2048        _compared_to_operator: Optional[OperatorType] = None, 
    2049        _compared_to_type: Optional[TypeEngine[Any]] = None, 
    2050        _is_crud: bool = False, 
    2051    ): 
    2052        if required is _NoArg.NO_ARG: 
    2053            required = value is _NoArg.NO_ARG and callable_ is None 
    2054        if value is _NoArg.NO_ARG: 
    2055            value = None 
    2056 
    2057        if quote is not None: 
    2058            key = quoted_name.construct(key, quote) 
    2059 
    2060        if unique: 
    2061            self.key, self._anon_map_key = ( 
    2062                _anonymous_label.safe_construct_with_key( 
    2063                    id(self), 
    2064                    ( 
    2065                        key 
    2066                        if key is not None 
    2067                        and not isinstance(key, _anonymous_label) 
    2068                        else "param" 
    2069                    ), 
    2070                    sanitize_key=True, 
    2071                ) 
    2072            ) 
    2073        elif key: 
    2074            self.key = key 
    2075        else: 
    2076            self.key, self._anon_map_key = ( 
    2077                _anonymous_label.safe_construct_with_key(id(self), "param") 
    2078            ) 
    2079 
    2080        # identifying key that won't change across 
    2081        # clones, used to identify the bind's logical 
    2082        # identity 
    2083        self._identifying_key = self.key 
    2084 
    2085        # key that was passed in the first place, used to 
    2086        # generate new keys 
    2087        self._orig_key = key or "param" 
    2088 
    2089        self.unique = unique 
    2090        self.value = value 
    2091        self.callable = callable_ 
    2092        self.isoutparam = isoutparam 
    2093        self.required = required 
    2094 
    2095        # indicate an "expanding" parameter; the compiler sets this 
    2096        # automatically in the compiler _render_in_expr_w_bindparam method 
    2097        # for an IN expression 
    2098        self.expanding = expanding 
    2099 
    2100        # this is another hint to help w/ expanding and is typically 
    2101        # set in the compiler _render_in_expr_w_bindparam method for an 
    2102        # IN expression 
    2103        self.expand_op = None 
    2104 
    2105        self.literal_execute = literal_execute 
    2106        if _is_crud: 
    2107            self._is_crud = True 
    2108 
    2109        if type_ is None: 
    2110            if expanding: 
    2111                if value: 
    2112                    check_value = value[0] 
    2113                else: 
    2114                    check_value = type_api._NO_VALUE_IN_LIST 
    2115            else: 
    2116                check_value = value 
    2117            if _compared_to_type is not None: 
    2118                self.type = _compared_to_type.coerce_compared_value( 
    2119                    _compared_to_operator, check_value 
    2120                ) 
    2121            else: 
    2122                self.type = type_api._resolve_value_to_type(check_value) 
    2123        elif isinstance(type_, type): 
    2124            self.type = type_() 
    2125        elif is_tuple_type(type_): 
    2126            if value: 
    2127                if expanding: 
    2128                    check_value = value[0] 
    2129                else: 
    2130                    check_value = value 
    2131                cast("BindParameter[TupleAny]", self).type = ( 
    2132                    type_._resolve_values_to_types(check_value) 
    2133                ) 
    2134            else: 
    2135                cast("BindParameter[TupleAny]", self).type = type_ 
    2136        else: 
    2137            self.type = type_ 
    2138 
    2139    def _with_value(self, value, maintain_key=False, required=NO_ARG): 
    2140        """Return a copy of this :class:`.BindParameter` with the given value 
    2141        set. 
    2142        """ 
    2143        cloned = self._clone(maintain_key=maintain_key) 
    2144        cloned.value = value 
    2145        cloned.callable = None 
    2146        cloned.required = required if required is not NO_ARG else self.required 
    2147        if cloned.type is type_api.NULLTYPE: 
    2148            cloned.type = type_api._resolve_value_to_type(value) 
    2149        return cloned 
    2150 
    2151    @property 
    2152    def effective_value(self) -> Optional[_T]: 
    2153        """Return the value of this bound parameter, 
    2154        taking into account if the ``callable`` parameter 
    2155        was set. 
    2156 
    2157        The ``callable`` value will be evaluated 
    2158        and returned if present, else ``value``. 
    2159 
    2160        """ 
    2161        if self.callable: 
    2162            # TODO: set up protocol for bind parameter callable 
    2163            return self.callable()  # type: ignore 
    2164        else: 
    2165            return self.value 
    2166 
    2167    def render_literal_execute(self) -> Self: 
    2168        """Produce a copy of this bound parameter that will enable the 
    2169        :paramref:`_sql.BindParameter.literal_execute` flag. 
    2170 
    2171        The :paramref:`_sql.BindParameter.literal_execute` flag will 
    2172        have the effect of the parameter rendered in the compiled SQL 
    2173        string using ``[POSTCOMPILE]`` form, which is a special form that 
    2174        is converted to be a rendering of the literal value of the parameter 
    2175        at SQL execution time.    The rationale is to support caching 
    2176        of SQL statement strings that can embed per-statement literal values, 
    2177        such as LIMIT and OFFSET parameters, in the final SQL string that 
    2178        is passed to the DBAPI.   Dialects in particular may want to use 
    2179        this method within custom compilation schemes. 
    2180 
    2181        .. versionadded:: 1.4.5 
    2182 
    2183        .. seealso:: 
    2184 
    2185            :ref:`engine_thirdparty_caching` 
    2186 
    2187        """ 
    2188        c: Self = ClauseElement._clone(self) 
    2189        c.literal_execute = True 
    2190        return c 
    2191 
    2192    def _negate_in_binary(self, negated_op, original_op): 
    2193        if self.expand_op is original_op: 
    2194            bind = self._clone() 
    2195            bind.expand_op = negated_op 
    2196            return bind 
    2197        else: 
    2198            return self 
    2199 
    2200    def _with_binary_element_type(self, type_: TypeEngine[Any]) -> Self: 
    2201        c: Self = ClauseElement._clone(self) 
    2202        c.type = type_ 
    2203        return c 
    2204 
    2205    def _clone(self, maintain_key: bool = False, **kw: Any) -> Self: 
    2206        c: Self = ClauseElement._clone(self, **kw) 
    2207        # ensure all the BindParameter objects stay in cloned set. 
    2208        # in #7823, we changed "clone" so that a clone only keeps a reference 
    2209        # to the "original" element, since for column correspondence, that's 
    2210        # all we need.   However, for BindParam, _cloned_set is used by 
    2211        # the "cache key bind match" lookup, which means if any of those 
    2212        # interim BindParameter objects became part of a cache key in the 
    2213        # cache, we need it.  So here, make sure all clones keep carrying 
    2214        # forward. 
    2215        c._cloned_set.update(self._cloned_set) 
    2216        if not maintain_key and self.unique: 
    2217            c.key, c._anon_map_key = _anonymous_label.safe_construct_with_key( 
    2218                id(c), c._orig_key or "param", sanitize_key=True 
    2219            ) 
    2220        return c 
    2221 
    2222    def _gen_cache_key(self, anon_map, bindparams): 
    2223        _gen_cache_ok = self.__class__.__dict__.get("inherit_cache", False) 
    2224 
    2225        if not _gen_cache_ok: 
    2226            if anon_map is not None: 
    2227                anon_map[NO_CACHE] = True 
    2228            return None 
    2229 
    2230        id_, found = anon_map.get_anon(self) 
    2231        if found: 
    2232            return (id_, self.__class__) 
    2233 
    2234        if bindparams is not None: 
    2235            bindparams.append(self) 
    2236 
    2237        return ( 
    2238            id_, 
    2239            self.__class__, 
    2240            self.type._static_cache_key, 
    2241            ( 
    2242                anon_map[self._anon_map_key] 
    2243                if self._anon_map_key is not None 
    2244                else self.key 
    2245            ), 
    2246            self.literal_execute, 
    2247        ) 
    2248 
    2249    def _convert_to_unique(self): 
    2250        if not self.unique: 
    2251            self.unique = True 
    2252            self.key, self._anon_map_key = ( 
    2253                _anonymous_label.safe_construct_with_key( 
    2254                    id(self), self._orig_key or "param", sanitize_key=True 
    2255                ) 
    2256            ) 
    2257 
    2258    def __getstate__(self): 
    2259        """execute a deferred value for serialization purposes.""" 
    2260 
    2261        d = self.__dict__.copy() 
    2262        v = self.value 
    2263        if self.callable: 
    2264            v = self.callable() 
    2265            d["callable"] = None 
    2266        d["value"] = v 
    2267        return d 
    2268 
    2269    def __setstate__(self, state): 
    2270        if state.get("unique", False): 
    2271            anon_and_key = _anonymous_label.safe_construct_with_key( 
    2272                id(self), state.get("_orig_key", "param"), sanitize_key=True 
    2273            ) 
    2274            state["key"], state["_anon_map_key"] = anon_and_key 
    2275        self.__dict__.update(state) 
    2276 
    2277    def __repr__(self): 
    2278        return "%s(%r, %r, type_=%r)" % ( 
    2279            self.__class__.__name__, 
    2280            self.key, 
    2281            self.value, 
    2282            self.type, 
    2283        ) 
    2284 
    2285 
    2286class TypeClause(DQLDMLClauseElement): 
    2287    """Handle a type keyword in a SQL statement. 
    2288 
    2289    Used by the ``Case`` statement. 
    2290 
    2291    """ 
    2292 
    2293    __visit_name__ = "typeclause" 
    2294 
    2295    _traverse_internals: _TraverseInternalsType = [ 
    2296        ("type", InternalTraversal.dp_type) 
    2297    ] 
    2298    type: TypeEngine[Any] 
    2299 
    2300    def __init__(self, type_: TypeEngine[Any]): 
    2301        self.type = type_ 
    2302 
    2303 
    2304class TextClause( 
    2305    roles.DDLConstraintColumnRole, 
    2306    roles.DDLExpressionRole, 
    2307    roles.StatementOptionRole, 
    2308    roles.WhereHavingRole, 
    2309    roles.OrderByRole, 
    2310    roles.FromClauseRole, 
    2311    roles.SelectStatementRole, 
    2312    roles.InElementRole, 
    2313    Generative, 
    2314    Executable, 
    2315    DQLDMLClauseElement, 
    2316    roles.BinaryElementRole[Any], 
    2317    inspection.Inspectable["TextClause"], 
    2318): 
    2319    """Represent a literal SQL text fragment. 
    2320 
    2321    E.g.:: 
    2322 
    2323        from sqlalchemy import text 
    2324 
    2325        t = text("SELECT * FROM users") 
    2326        result = connection.execute(t) 
    2327 
    2328    The :class:`_expression.TextClause` construct is produced using the 
    2329    :func:`_expression.text` 
    2330    function; see that function for full documentation. 
    2331 
    2332    .. seealso:: 
    2333 
    2334        :func:`_expression.text` 
    2335 
    2336    """ 
    2337 
    2338    __visit_name__ = "textclause" 
    2339 
    2340    _traverse_internals: _TraverseInternalsType = [ 
    2341        ("_bindparams", InternalTraversal.dp_string_clauseelement_dict), 
    2342        ("text", InternalTraversal.dp_string), 
    2343    ] + Executable._executable_traverse_internals 
    2344 
    2345    _is_text_clause = True 
    2346 
    2347    _is_textual = True 
    2348 
    2349    _bind_params_regex = re.compile(r"(?<![:\w\x5c]):(\w+)(?!:)", re.UNICODE) 
    2350    _is_implicitly_boolean = False 
    2351 
    2352    _render_label_in_columns_clause = False 
    2353 
    2354    _omit_from_statements = False 
    2355 
    2356    _is_collection_aggregate = False 
    2357 
    2358    @property 
    2359    def _hide_froms(self) -> Iterable[FromClause]: 
    2360        return () 
    2361 
    2362    def __and__(self, other): 
    2363        # support use in select.where(), query.filter() 
    2364        return and_(self, other) 
    2365 
    2366    @property 
    2367    def _select_iterable(self) -> _SelectIterable: 
    2368        return (self,) 
    2369 
    2370    # help in those cases where text() is 
    2371    # interpreted in a column expression situation 
    2372    key: Optional[str] = None 
    2373    _label: Optional[str] = None 
    2374 
    2375    _allow_label_resolve = False 
    2376 
    2377    @property 
    2378    def _is_star(self):  # type: ignore[override] 
    2379        return self.text == "*" 
    2380 
    2381    def __init__(self, text: str): 
    2382        self._bindparams: Dict[str, BindParameter[Any]] = {} 
    2383 
    2384        def repl(m): 
    2385            self._bindparams[m.group(1)] = BindParameter(m.group(1)) 
    2386            return ":%s" % m.group(1) 
    2387 
    2388        # scan the string and search for bind parameter names, add them 
    2389        # to the list of bindparams 
    2390        self.text = self._bind_params_regex.sub(repl, text) 
    2391 
    2392    @_generative 
    2393    def bindparams( 
    2394        self, 
    2395        *binds: BindParameter[Any], 
    2396        **names_to_values: Any, 
    2397    ) -> Self: 
    2398        """Establish the values and/or types of bound parameters within 
    2399        this :class:`_expression.TextClause` construct. 
    2400 
    2401        Given a text construct such as:: 
    2402 
    2403            from sqlalchemy import text 
    2404 
    2405            stmt = text( 
    2406                "SELECT id, name FROM user WHERE name=:name AND timestamp=:timestamp" 
    2407            ) 
    2408 
    2409        the :meth:`_expression.TextClause.bindparams` 
    2410        method can be used to establish 
    2411        the initial value of ``:name`` and ``:timestamp``, 
    2412        using simple keyword arguments:: 
    2413 
    2414            stmt = stmt.bindparams( 
    2415                name="jack", timestamp=datetime.datetime(2012, 10, 8, 15, 12, 5) 
    2416            ) 
    2417 
    2418        Where above, new :class:`.BindParameter` objects 
    2419        will be generated with the names ``name`` and ``timestamp``, and 
    2420        values of ``jack`` and ``datetime.datetime(2012, 10, 8, 15, 12, 5)``, 
    2421        respectively.  The types will be 
    2422        inferred from the values given, in this case :class:`.String` and 
    2423        :class:`.DateTime`. 
    2424 
    2425        When specific typing behavior is needed, the positional ``*binds`` 
    2426        argument can be used in which to specify :func:`.bindparam` constructs 
    2427        directly.  These constructs must include at least the ``key`` 
    2428        argument, then an optional value and type:: 
    2429 
    2430            from sqlalchemy import bindparam 
    2431 
    2432            stmt = stmt.bindparams( 
    2433                bindparam("name", value="jack", type_=String), 
    2434                bindparam("timestamp", type_=DateTime), 
    2435            ) 
    2436 
    2437        Above, we specified the type of :class:`.DateTime` for the 
    2438        ``timestamp`` bind, and the type of :class:`.String` for the ``name`` 
    2439        bind.  In the case of ``name`` we also set the default value of 
    2440        ``"jack"``. 
    2441 
    2442        Additional bound parameters can be supplied at statement execution 
    2443        time, e.g.:: 
    2444 
    2445            result = connection.execute( 
    2446                stmt, timestamp=datetime.datetime(2012, 10, 8, 15, 12, 5) 
    2447            ) 
    2448 
    2449        The :meth:`_expression.TextClause.bindparams` 
    2450        method can be called repeatedly, 
    2451        where it will re-use existing :class:`.BindParameter` objects to add 
    2452        new information.  For example, we can call 
    2453        :meth:`_expression.TextClause.bindparams` 
    2454        first with typing information, and a 
    2455        second time with value information, and it will be combined:: 
    2456 
    2457            stmt = text( 
    2458                "SELECT id, name FROM user WHERE name=:name " 
    2459                "AND timestamp=:timestamp" 
    2460            ) 
    2461            stmt = stmt.bindparams( 
    2462                bindparam("name", type_=String), bindparam("timestamp", type_=DateTime) 
    2463            ) 
    2464            stmt = stmt.bindparams( 
    2465                name="jack", timestamp=datetime.datetime(2012, 10, 8, 15, 12, 5) 
    2466            ) 
    2467 
    2468        The :meth:`_expression.TextClause.bindparams` 
    2469        method also supports the concept of 
    2470        **unique** bound parameters.  These are parameters that are 
    2471        "uniquified" on name at statement compilation time, so that  multiple 
    2472        :func:`_expression.text` 
    2473        constructs may be combined together without the names 
    2474        conflicting.  To use this feature, specify the 
    2475        :paramref:`.BindParameter.unique` flag on each :func:`.bindparam` 
    2476        object:: 
    2477 
    2478            stmt1 = text("select id from table where name=:name").bindparams( 
    2479                bindparam("name", value="name1", unique=True) 
    2480            ) 
    2481            stmt2 = text("select id from table where name=:name").bindparams( 
    2482                bindparam("name", value="name2", unique=True) 
    2483            ) 
    2484 
    2485            union = union_all(stmt1.columns(column("id")), stmt2.columns(column("id"))) 
    2486 
    2487        The above statement will render as: 
    2488 
    2489        .. sourcecode:: sql 
    2490 
    2491            select id from table where name=:name_1 
    2492            UNION ALL select id from table where name=:name_2 
    2493 
    2494        """  # noqa: E501 
    2495        self._bindparams = new_params = self._bindparams.copy() 
    2496 
    2497        for bind in binds: 
    2498            try: 
    2499                # the regex used for text() currently will not match 
    2500                # a unique/anonymous key in any case, so use the _orig_key 
    2501                # so that a text() construct can support unique parameters 
    2502                existing = new_params[bind._orig_key] 
    2503            except KeyError as err: 
    2504                raise exc.ArgumentError( 
    2505                    "This text() construct doesn't define a " 
    2506                    "bound parameter named %r" % bind._orig_key 
    2507                ) from err 
    2508            else: 
    2509                new_params[existing._orig_key] = bind 
    2510 
    2511        for key, value in names_to_values.items(): 
    2512            try: 
    2513                existing = new_params[key] 
    2514            except KeyError as err: 
    2515                raise exc.ArgumentError( 
    2516                    "This text() construct doesn't define a " 
    2517                    "bound parameter named %r" % key 
    2518                ) from err 
    2519            else: 
    2520                new_params[key] = existing._with_value(value, required=False) 
    2521        return self 
    2522 
    2523    @util.preload_module("sqlalchemy.sql.selectable") 
    2524    def columns( 
    2525        self, 
    2526        *cols: _ColumnExpressionArgument[Any], 
    2527        **types: _TypeEngineArgument[Any], 
    2528    ) -> TextualSelect: 
    2529        r"""Turn this :class:`_expression.TextClause` object into a 
    2530        :class:`_expression.TextualSelect` 
    2531        object that serves the same role as a SELECT 
    2532        statement. 
    2533 
    2534        The :class:`_expression.TextualSelect` is part of the 
    2535        :class:`_expression.SelectBase` 
    2536        hierarchy and can be embedded into another statement by using the 
    2537        :meth:`_expression.TextualSelect.subquery` method to produce a 
    2538        :class:`.Subquery` 
    2539        object, which can then be SELECTed from. 
    2540 
    2541        This function essentially bridges the gap between an entirely 
    2542        textual SELECT statement and the SQL expression language concept 
    2543        of a "selectable":: 
    2544 
    2545            from sqlalchemy.sql import column, text 
    2546 
    2547            stmt = text("SELECT id, name FROM some_table") 
    2548            stmt = stmt.columns(column("id"), column("name")).subquery("st") 
    2549 
    2550            stmt = ( 
    2551                select(mytable) 
    2552                .select_from(mytable.join(stmt, mytable.c.name == stmt.c.name)) 
    2553                .where(stmt.c.id > 5) 
    2554            ) 
    2555 
    2556        Above, we pass a series of :func:`_expression.column` elements to the 
    2557        :meth:`_expression.TextClause.columns` method positionally.  These 
    2558        :func:`_expression.column` 
    2559        elements now become first class elements upon the 
    2560        :attr:`_expression.TextualSelect.selected_columns` column collection, 
    2561        which then 
    2562        become part of the :attr:`.Subquery.c` collection after 
    2563        :meth:`_expression.TextualSelect.subquery` is invoked. 
    2564 
    2565        The column expressions we pass to 
    2566        :meth:`_expression.TextClause.columns` may 
    2567        also be typed; when we do so, these :class:`.TypeEngine` objects become 
    2568        the effective return type of the column, so that SQLAlchemy's 
    2569        result-set-processing systems may be used on the return values. 
    2570        This is often needed for types such as date or boolean types, as well 
    2571        as for unicode processing on some dialect configurations:: 
    2572 
    2573            stmt = text("SELECT id, name, timestamp FROM some_table") 
    2574            stmt = stmt.columns( 
    2575                column("id", Integer), 
    2576                column("name", Unicode), 
    2577                column("timestamp", DateTime), 
    2578            ) 
    2579 
    2580            for id, name, timestamp in connection.execute(stmt): 
    2581                print(id, name, timestamp) 
    2582 
    2583        As a shortcut to the above syntax, keyword arguments referring to 
    2584        types alone may be used, if only type conversion is needed:: 
    2585 
    2586            stmt = text("SELECT id, name, timestamp FROM some_table") 
    2587            stmt = stmt.columns(id=Integer, name=Unicode, timestamp=DateTime) 
    2588 
    2589            for id, name, timestamp in connection.execute(stmt): 
    2590                print(id, name, timestamp) 
    2591 
    2592        The positional form of :meth:`_expression.TextClause.columns` 
    2593        also provides the 
    2594        unique feature of **positional column targeting**, which is 
    2595        particularly useful when using the ORM with complex textual queries. If 
    2596        we specify the columns from our model to 
    2597        :meth:`_expression.TextClause.columns`, 
    2598        the result set will match to those columns positionally, meaning the 
    2599        name or origin of the column in the textual SQL doesn't matter:: 
    2600 
    2601            stmt = text( 
    2602                "SELECT users.id, addresses.id, users.id, " 
    2603                "users.name, addresses.email_address AS email " 
    2604                "FROM users JOIN addresses ON users.id=addresses.user_id " 
    2605                "WHERE users.id = 1" 
    2606            ).columns( 
    2607                User.id, 
    2608                Address.id, 
    2609                Address.user_id, 
    2610                User.name, 
    2611                Address.email_address, 
    2612            ) 
    2613 
    2614            query = ( 
    2615                session.query(User) 
    2616                .from_statement(stmt) 
    2617                .options(contains_eager(User.addresses)) 
    2618            ) 
    2619 
    2620        The :meth:`_expression.TextClause.columns` method provides a direct 
    2621        route to calling :meth:`_expression.FromClause.subquery` as well as 
    2622        :meth:`_expression.SelectBase.cte` 
    2623        against a textual SELECT statement:: 
    2624 
    2625            stmt = stmt.columns(id=Integer, name=String).cte("st") 
    2626 
    2627            stmt = select(sometable).where(sometable.c.id == stmt.c.id) 
    2628 
    2629        :param \*cols: A series of :class:`_expression.ColumnElement` objects, 
    2630         typically 
    2631         :class:`_schema.Column` objects from a :class:`_schema.Table` 
    2632         or ORM level 
    2633         column-mapped attributes, representing a set of columns that this 
    2634         textual string will SELECT from. 
    2635 
    2636        :param \**types: A mapping of string names to :class:`.TypeEngine` 
    2637         type objects indicating the datatypes to use for names that are 
    2638         SELECTed from the textual string.  Prefer to use the ``*cols`` 
    2639         argument as it also indicates positional ordering. 
    2640 
    2641        """ 
    2642        selectable = util.preloaded.sql_selectable 
    2643 
    2644        input_cols: List[NamedColumn[Any]] = [ 
    2645            coercions.expect(roles.LabeledColumnExprRole, col) for col in cols 
    2646        ] 
    2647 
    2648        positional_input_cols = [ 
    2649            ( 
    2650                ColumnClause(col.key, types.pop(col.key)) 
    2651                if col.key in types 
    2652                else col 
    2653            ) 
    2654            for col in input_cols 
    2655        ] 
    2656        keyed_input_cols: List[NamedColumn[Any]] = [ 
    2657            ColumnClause(key, type_) for key, type_ in types.items() 
    2658        ] 
    2659 
    2660        elem = selectable.TextualSelect.__new__(selectable.TextualSelect) 
    2661        elem._init( 
    2662            self, 
    2663            positional_input_cols + keyed_input_cols, 
    2664            positional=bool(positional_input_cols) and not keyed_input_cols, 
    2665        ) 
    2666        return elem 
    2667 
    2668    @property 
    2669    def type(self) -> TypeEngine[Any]: 
    2670        return type_api.NULLTYPE 
    2671 
    2672    @property 
    2673    def comparator(self): 
    2674        # TODO: this seems wrong, it seems like we might not 
    2675        # be using this method. 
    2676        return self.type.comparator_factory(self)  # type: ignore 
    2677 
    2678    def self_group( 
    2679        self, against: Optional[OperatorType] = None 
    2680    ) -> Union[Self, Grouping[Any]]: 
    2681        if against is operators.in_op: 
    2682            return Grouping(self) 
    2683        else: 
    2684            return self 
    2685 
    2686 
    2687class Null(SingletonConstant, roles.ConstExprRole[None], ColumnElement[None]): 
    2688    """Represent the NULL keyword in a SQL statement. 
    2689 
    2690    :class:`.Null` is accessed as a constant via the 
    2691    :func:`.null` function. 
    2692 
    2693    """ 
    2694 
    2695    __visit_name__ = "null" 
    2696 
    2697    _traverse_internals: _TraverseInternalsType = [] 
    2698    _singleton: Null 
    2699 
    2700    if not TYPE_CHECKING: 
    2701 
    2702        @util.memoized_property 
    2703        def type(self) -> TypeEngine[_T]:  # noqa: A001 
    2704            return type_api.NULLTYPE 
    2705 
    2706    @classmethod 
    2707    def _instance(cls) -> Null: 
    2708        """Return a constant :class:`.Null` construct.""" 
    2709 
    2710        return Null._singleton 
    2711 
    2712 
    2713Null._create_singleton() 
    2714 
    2715 
    2716class False_( 
    2717    SingletonConstant, roles.ConstExprRole[bool], ColumnElement[bool] 
    2718): 
    2719    """Represent the ``false`` keyword, or equivalent, in a SQL statement. 
    2720 
    2721    :class:`.False_` is accessed as a constant via the 
    2722    :func:`.false` function. 
    2723 
    2724    """ 
    2725 
    2726    __visit_name__ = "false" 
    2727    _traverse_internals: _TraverseInternalsType = [] 
    2728    _singleton: False_ 
    2729 
    2730    if not TYPE_CHECKING: 
    2731 
    2732        @util.memoized_property 
    2733        def type(self) -> TypeEngine[_T]:  # noqa: A001 
    2734            return type_api.BOOLEANTYPE 
    2735 
    2736    def _negate(self) -> True_: 
    2737        return True_._singleton 
    2738 
    2739    @classmethod 
    2740    def _instance(cls) -> False_: 
    2741        return False_._singleton 
    2742 
    2743 
    2744False_._create_singleton() 
    2745 
    2746 
    2747class True_(SingletonConstant, roles.ConstExprRole[bool], ColumnElement[bool]): 
    2748    """Represent the ``true`` keyword, or equivalent, in a SQL statement. 
    2749 
    2750    :class:`.True_` is accessed as a constant via the 
    2751    :func:`.true` function. 
    2752 
    2753    """ 
    2754 
    2755    __visit_name__ = "true" 
    2756 
    2757    _traverse_internals: _TraverseInternalsType = [] 
    2758    _singleton: True_ 
    2759 
    2760    if not TYPE_CHECKING: 
    2761 
    2762        @util.memoized_property 
    2763        def type(self) -> TypeEngine[_T]:  # noqa: A001 
    2764            return type_api.BOOLEANTYPE 
    2765 
    2766    def _negate(self) -> False_: 
    2767        return False_._singleton 
    2768 
    2769    @classmethod 
    2770    def _ifnone( 
    2771        cls, other: Optional[ColumnElement[Any]] 
    2772    ) -> ColumnElement[Any]: 
    2773        if other is None: 
    2774            return cls._instance() 
    2775        else: 
    2776            return other 
    2777 
    2778    @classmethod 
    2779    def _instance(cls) -> True_: 
    2780        return True_._singleton 
    2781 
    2782 
    2783True_._create_singleton() 
    2784 
    2785 
    2786class ElementList(DQLDMLClauseElement): 
    2787    """Describe a list of clauses that will be space separated. 
    2788 
    2789    This is a minimal version of :class:`.ClauseList` which is used by 
    2790    the :class:`.HasSyntaxExtension` class.  It does not do any coercions 
    2791    so should be used internally only. 
    2792 
    2793    .. versionadded:: 2.1 
    2794 
    2795    """ 
    2796 
    2797    __visit_name__ = "element_list" 
    2798 
    2799    _traverse_internals: _TraverseInternalsType = [ 
    2800        ("clauses", InternalTraversal.dp_clauseelement_tuple), 
    2801    ] 
    2802 
    2803    clauses: typing_Tuple[ClauseElement, ...] 
    2804 
    2805    def __init__(self, clauses: Sequence[ClauseElement]): 
    2806        self.clauses = tuple(clauses) 
    2807 
    2808 
    2809class OrderByList( 
    2810    roles.OrderByRole, 
    2811    operators.OrderingOperators, 
    2812    DQLDMLClauseElement, 
    2813): 
    2814    """Describe a list of clauses that will be comma separated to nest 
    2815    within an ORDER BY. 
    2816 
    2817    .. versionadded:: 2.1 
    2818 
    2819    """ 
    2820 
    2821    __visit_name__ = "order_by_list" 
    2822 
    2823    _traverse_internals: _TraverseInternalsType = [ 
    2824        ("clauses", InternalTraversal.dp_clauseelement_tuple), 
    2825    ] 
    2826 
    2827    clauses: List[ColumnElement[Any]] 
    2828 
    2829    def __init__( 
    2830        self, 
    2831        clauses: Iterable[Union[OrderByList, _ColumnExpressionArgument[Any]]], 
    2832    ): 
    2833        text_converter_role: Type[roles.SQLRole] = roles.ByOfRole 
    2834        self._text_converter_role = text_converter_role 
    2835 
    2836        self.clauses = [ 
    2837            coercions.expect( 
    2838                text_converter_role, clause, apply_propagate_attrs=self 
    2839            ) 
    2840            for clause in clauses 
    2841        ] 
    2842 
    2843    def __iter__(self) -> Iterator[ColumnElement[Any]]: 
    2844        return iter(self.clauses) 
    2845 
    2846    def __len__(self) -> int: 
    2847        return len(self.clauses) 
    2848 
    2849    @property 
    2850    def _select_iterable(self) -> _SelectIterable: 
    2851        return itertools.chain.from_iterable( 
    2852            [elem._select_iterable for elem in self.clauses] 
    2853        ) 
    2854 
    2855    @util.ro_non_memoized_property 
    2856    def _from_objects(self) -> List[FromClause]: 
    2857        return list(itertools.chain(*[c._from_objects for c in self.clauses])) 
    2858 
    2859    def self_group( 
    2860        self, against: Optional[OperatorType] = None 
    2861    ) -> Union[Self, Grouping[Any]]: 
    2862        return self 
    2863 
    2864    def desc(self) -> OrderByList: 
    2865        return OrderByList([e.desc() for e in self.clauses]) 
    2866 
    2867    def asc(self) -> OrderByList: 
    2868        return OrderByList([e.asc() for e in self.clauses]) 
    2869 
    2870    def nulls_first(self) -> OrderByList: 
    2871        return OrderByList([e.nulls_first() for e in self.clauses]) 
    2872 
    2873    def nulls_last(self) -> OrderByList: 
    2874        return OrderByList([e.nulls_last() for e in self.clauses]) 
    2875 
    2876 
    2877class ClauseList( 
    2878    roles.InElementRole, 
    2879    roles.OrderByRole, 
    2880    roles.ColumnsClauseRole, 
    2881    roles.DMLColumnRole, 
    2882    DQLDMLClauseElement, 
    2883): 
    2884    """Describe a list of clauses, separated by an operator. 
    2885 
    2886    By default, is comma-separated, such as a column listing. 
    2887 
    2888    """ 
    2889 
    2890    __visit_name__ = "clauselist" 
    2891 
    2892    # Used by ORM context.py to identify ClauseList objects in legacy 
    2893    # composite attribute queries (see test_query_cols_legacy test) 
    2894    _is_clause_list = True 
    2895 
    2896    _traverse_internals: _TraverseInternalsType = [ 
    2897        ("clauses", InternalTraversal.dp_clauseelement_list), 
    2898        ("operator", InternalTraversal.dp_operator), 
    2899    ] 
    2900 
    2901    clauses: List[ColumnElement[Any]] 
    2902 
    2903    def __init__( 
    2904        self, 
    2905        *clauses: _ColumnExpressionArgument[Any], 
    2906        operator: OperatorType = operators.comma_op, 
    2907        group: bool = True, 
    2908        group_contents: bool = True, 
    2909        _literal_as_text_role: Type[roles.SQLRole] = roles.WhereHavingRole, 
    2910    ): 
    2911        self.operator = operator 
    2912        self.group = group 
    2913        self.group_contents = group_contents 
    2914        clauses_iterator: Iterable[_ColumnExpressionArgument[Any]] = clauses 
    2915        text_converter_role: Type[roles.SQLRole] = _literal_as_text_role 
    2916        self._text_converter_role = text_converter_role 
    2917 
    2918        if self.group_contents: 
    2919            self.clauses = [ 
    2920                coercions.expect( 
    2921                    text_converter_role, clause, apply_propagate_attrs=self 
    2922                ).self_group(against=self.operator) 
    2923                for clause in clauses_iterator 
    2924            ] 
    2925        else: 
    2926            self.clauses = [ 
    2927                coercions.expect( 
    2928                    text_converter_role, clause, apply_propagate_attrs=self 
    2929                ) 
    2930                for clause in clauses_iterator 
    2931            ] 
    2932        self._is_implicitly_boolean = operators.is_boolean(self.operator) 
    2933 
    2934    @classmethod 
    2935    def _construct_raw( 
    2936        cls, 
    2937        operator: OperatorType, 
    2938        clauses: Optional[Sequence[ColumnElement[Any]]] = None, 
    2939    ) -> ClauseList: 
    2940        self = cls.__new__(cls) 
    2941        self.clauses = list(clauses) if clauses else [] 
    2942        self.group = True 
    2943        self.operator = operator 
    2944        self.group_contents = True 
    2945        self._is_implicitly_boolean = False 
    2946        return self 
    2947 
    2948    def __iter__(self) -> Iterator[ColumnElement[Any]]: 
    2949        return iter(self.clauses) 
    2950 
    2951    def __len__(self) -> int: 
    2952        return len(self.clauses) 
    2953 
    2954    @property 
    2955    def _select_iterable(self) -> _SelectIterable: 
    2956        return itertools.chain.from_iterable( 
    2957            [elem._select_iterable for elem in self.clauses] 
    2958        ) 
    2959 
    2960    def append(self, clause): 
    2961        if self.group_contents: 
    2962            self.clauses.append( 
    2963                coercions.expect(self._text_converter_role, clause).self_group( 
    2964                    against=self.operator 
    2965                ) 
    2966            ) 
    2967        else: 
    2968            self.clauses.append( 
    2969                coercions.expect(self._text_converter_role, clause) 
    2970            ) 
    2971 
    2972    @util.ro_non_memoized_property 
    2973    def _from_objects(self) -> List[FromClause]: 
    2974        return list(itertools.chain(*[c._from_objects for c in self.clauses])) 
    2975 
    2976    def self_group( 
    2977        self, against: Optional[OperatorType] = None 
    2978    ) -> Union[Self, Grouping[Any]]: 
    2979        if self.group and operators.is_precedent(self.operator, against): 
    2980            return Grouping(self) 
    2981        else: 
    2982            return self 
    2983 
    2984 
    2985class OperatorExpression(ColumnElement[_T]): 
    2986    """base for expressions that contain an operator and operands 
    2987 
    2988    .. versionadded:: 2.0 
    2989 
    2990    """ 
    2991 
    2992    operator: OperatorType 
    2993    type: TypeEngine[_T] 
    2994 
    2995    group: bool = True 
    2996 
    2997    @property 
    2998    def is_comparison(self): 
    2999        return operators.is_comparison(self.operator) 
    3000 
    3001    def self_group( 
    3002        self, against: Optional[OperatorType] = None 
    3003    ) -> Union[Self, Grouping[_T]]: 
    3004        if ( 
    3005            self.group 
    3006            and operators.is_precedent(self.operator, against) 
    3007            or ( 
    3008                # a negate against a non-boolean operator 
    3009                # doesn't make too much sense but we should 
    3010                # group for that 
    3011                against is operators.inv 
    3012                and not operators.is_boolean(self.operator) 
    3013            ) 
    3014        ): 
    3015            return Grouping(self) 
    3016        else: 
    3017            return self 
    3018 
    3019    @property 
    3020    def _flattened_operator_clauses( 
    3021        self, 
    3022    ) -> typing_Tuple[ColumnElement[Any], ...]: 
    3023        raise NotImplementedError() 
    3024 
    3025    @classmethod 
    3026    def _construct_for_op( 
    3027        cls, 
    3028        left: ColumnElement[Any], 
    3029        right: ColumnElement[Any], 
    3030        op: OperatorType, 
    3031        *, 
    3032        type_: TypeEngine[_T], 
    3033        negate: Optional[OperatorType] = None, 
    3034        modifiers: Optional[Mapping[str, Any]] = None, 
    3035    ) -> OperatorExpression[_T]: 
    3036        if operators.is_associative(op): 
    3037            assert ( 
    3038                negate is None 
    3039            ), f"negate not supported for associative operator {op}" 
    3040 
    3041            multi = False 
    3042            if getattr( 
    3043                left, "operator", None 
    3044            ) is op and type_._compare_type_affinity(left.type): 
    3045                multi = True 
    3046                left_flattened = left._flattened_operator_clauses 
    3047            else: 
    3048                left_flattened = (left,) 
    3049 
    3050            if getattr( 
    3051                right, "operator", None 
    3052            ) is op and type_._compare_type_affinity(right.type): 
    3053                multi = True 
    3054                right_flattened = right._flattened_operator_clauses 
    3055            else: 
    3056                right_flattened = (right,) 
    3057 
    3058            if multi: 
    3059                return ExpressionClauseList._construct_for_list( 
    3060                    op, 
    3061                    type_, 
    3062                    *(left_flattened + right_flattened), 
    3063                ) 
    3064 
    3065        if right._is_collection_aggregate: 
    3066            negate = None 
    3067 
    3068        return BinaryExpression( 
    3069            left, right, op, type_=type_, negate=negate, modifiers=modifiers 
    3070        ) 
    3071 
    3072 
    3073class ExpressionClauseList(OperatorExpression[_T]): 
    3074    """Describe a list of clauses, separated by an operator, 
    3075    in a column expression context. 
    3076 
    3077    :class:`.ExpressionClauseList` differs from :class:`.ClauseList` in that 
    3078    it represents a column-oriented DQL expression only, not an open ended 
    3079    list of anything comma separated. 
    3080 
    3081    .. versionadded:: 2.0 
    3082 
    3083    """ 
    3084 
    3085    __visit_name__ = "expression_clauselist" 
    3086 
    3087    _traverse_internals: _TraverseInternalsType = [ 
    3088        ("clauses", InternalTraversal.dp_clauseelement_tuple), 
    3089        ("operator", InternalTraversal.dp_operator), 
    3090    ] 
    3091 
    3092    clauses: typing_Tuple[ColumnElement[Any], ...] 
    3093 
    3094    group: bool 
    3095 
    3096    def __init__( 
    3097        self, 
    3098        operator: OperatorType, 
    3099        *clauses: _ColumnExpressionArgument[Any], 
    3100        type_: Optional[_TypeEngineArgument[_T]] = None, 
    3101    ): 
    3102        self.operator = operator 
    3103 
    3104        self.clauses = tuple( 
    3105            coercions.expect( 
    3106                roles.ExpressionElementRole, clause, apply_propagate_attrs=self 
    3107            ) 
    3108            for clause in clauses 
    3109        ) 
    3110        self._is_implicitly_boolean = operators.is_boolean(self.operator) 
    3111        self.type = type_api.to_instance(type_)  # type: ignore 
    3112 
    3113    @property 
    3114    def _flattened_operator_clauses( 
    3115        self, 
    3116    ) -> typing_Tuple[ColumnElement[Any], ...]: 
    3117        return self.clauses 
    3118 
    3119    def __iter__(self) -> Iterator[ColumnElement[Any]]: 
    3120        return iter(self.clauses) 
    3121 
    3122    def __len__(self) -> int: 
    3123        return len(self.clauses) 
    3124 
    3125    @property 
    3126    def _select_iterable(self) -> _SelectIterable: 
    3127        return (self,) 
    3128 
    3129    @util.ro_non_memoized_property 
    3130    def _from_objects(self) -> List[FromClause]: 
    3131        return list(itertools.chain(*[c._from_objects for c in self.clauses])) 
    3132 
    3133    def _append_inplace(self, clause: ColumnElement[Any]) -> None: 
    3134        self.clauses += (clause,) 
    3135 
    3136    @classmethod 
    3137    def _construct_for_list( 
    3138        cls, 
    3139        operator: OperatorType, 
    3140        type_: TypeEngine[_T], 
    3141        *clauses: ColumnElement[Any], 
    3142        group: bool = True, 
    3143    ) -> ExpressionClauseList[_T]: 
    3144        self = cls.__new__(cls) 
    3145        self.group = group 
    3146        if group: 
    3147            self.clauses = tuple( 
    3148                c.self_group(against=operator) for c in clauses 
    3149            ) 
    3150        else: 
    3151            self.clauses = clauses 
    3152        self.operator = operator 
    3153        self.type = type_ 
    3154        for c in clauses: 
    3155            if c._propagate_attrs: 
    3156                self._propagate_attrs = c._propagate_attrs 
    3157                break 
    3158        return self 
    3159 
    3160    def _negate(self) -> Any: 
    3161        grouped = self.self_group(against=operators.inv) 
    3162        assert isinstance(grouped, ColumnElement) 
    3163        return UnaryExpression(grouped, operator=operators.inv) 
    3164 
    3165 
    3166class BooleanClauseList(ExpressionClauseList[bool]): 
    3167    __visit_name__ = "expression_clauselist" 
    3168    inherit_cache = True 
    3169 
    3170    def __init__(self, *arg, **kw): 
    3171        raise NotImplementedError( 
    3172            "BooleanClauseList has a private constructor" 
    3173        ) 
    3174 
    3175    @classmethod 
    3176    def _process_clauses_for_boolean( 
    3177        cls, 
    3178        operator: OperatorType, 
    3179        continue_on: Any, 
    3180        skip_on: Any, 
    3181        clauses: Iterable[ColumnElement[Any]], 
    3182    ) -> typing_Tuple[int, List[ColumnElement[Any]]]: 
    3183        has_continue_on = None 
    3184 
    3185        convert_clauses = [] 
    3186 
    3187        against = operators._asbool 
    3188        lcc = 0 
    3189 
    3190        for clause in clauses: 
    3191            if clause is continue_on: 
    3192                # instance of continue_on, like and_(x, y, True, z), store it 
    3193                # if we didn't find one already, we will use it if there 
    3194                # are no other expressions here. 
    3195                has_continue_on = clause 
    3196            elif clause is skip_on: 
    3197                # instance of skip_on, e.g. and_(x, y, False, z), cancels 
    3198                # the rest out 
    3199                convert_clauses = [clause] 
    3200                lcc = 1 
    3201                break 
    3202            else: 
    3203                if not lcc: 
    3204                    lcc = 1 
    3205                else: 
    3206                    against = operator 
    3207                    # technically this would be len(convert_clauses) + 1 
    3208                    # however this only needs to indicate "greater than one" 
    3209                    lcc = 2 
    3210                convert_clauses.append(clause) 
    3211 
    3212        if not convert_clauses and has_continue_on is not None: 
    3213            convert_clauses = [has_continue_on] 
    3214            lcc = 1 
    3215 
    3216        return lcc, [c.self_group(against=against) for c in convert_clauses] 
    3217 
    3218    @classmethod 
    3219    def _construct( 
    3220        cls, 
    3221        operator: OperatorType, 
    3222        continue_on: Any, 
    3223        skip_on: Any, 
    3224        initial_clause: Any = _NoArg.NO_ARG, 
    3225        *clauses: Any, 
    3226        **kw: Any, 
    3227    ) -> ColumnElement[Any]: 
    3228        if initial_clause is _NoArg.NO_ARG: 
    3229            # no elements period.  deprecated use case.  return an empty 
    3230            # ClauseList construct that generates nothing unless it has 
    3231            # elements added to it. 
    3232            name = operator.__name__ 
    3233 
    3234            util.warn_deprecated( 
    3235                f"Invoking {name}() without arguments is deprecated, and " 
    3236                f"will be disallowed in a future release.   For an empty " 
    3237                f"""{name}() construct, use '{name}({ 
    3238                    'true()' if continue_on is True_._singleton else 'false()' 
    3239                }, *args)' """ 
    3240                f"""or '{name}({ 
    3241                    'True' if continue_on is True_._singleton else 'False' 
    3242                }, *args)'.""", 
    3243                version="1.4", 
    3244            ) 
    3245            return cls._construct_raw(operator) 
    3246 
    3247        lcc, convert_clauses = cls._process_clauses_for_boolean( 
    3248            operator, 
    3249            continue_on, 
    3250            skip_on, 
    3251            [ 
    3252                coercions.expect(roles.WhereHavingRole, clause) 
    3253                for clause in util.coerce_generator_arg( 
    3254                    (initial_clause,) + clauses 
    3255                ) 
    3256            ], 
    3257        ) 
    3258 
    3259        if lcc > 1: 
    3260            # multiple elements.  Return regular BooleanClauseList 
    3261            # which will link elements against the operator. 
    3262 
    3263            flattened_clauses = itertools.chain.from_iterable( 
    3264                ( 
    3265                    (c for c in to_flat._flattened_operator_clauses) 
    3266                    if getattr(to_flat, "operator", None) is operator 
    3267                    else (to_flat,) 
    3268                ) 
    3269                for to_flat in convert_clauses 
    3270            ) 
    3271 
    3272            return cls._construct_raw(operator, flattened_clauses)  # type: ignore # noqa: E501 
    3273        else: 
    3274            assert lcc 
    3275            # just one element.  return it as a single boolean element, 
    3276            # not a list and discard the operator. 
    3277            return convert_clauses[0] 
    3278 
    3279    @classmethod 
    3280    def _construct_for_whereclause( 
    3281        cls, clauses: Iterable[ColumnElement[Any]] 
    3282    ) -> Optional[ColumnElement[bool]]: 
    3283        operator, continue_on, skip_on = ( 
    3284            operators.and_, 
    3285            True_._singleton, 
    3286            False_._singleton, 
    3287        ) 
    3288 
    3289        lcc, convert_clauses = cls._process_clauses_for_boolean( 
    3290            operator, 
    3291            continue_on, 
    3292            skip_on, 
    3293            clauses,  # these are assumed to be coerced already 
    3294        ) 
    3295 
    3296        if lcc > 1: 
    3297            # multiple elements.  Return regular BooleanClauseList 
    3298            # which will link elements against the operator. 
    3299            return cls._construct_raw(operator, convert_clauses) 
    3300        elif lcc == 1: 
    3301            # just one element.  return it as a single boolean element, 
    3302            # not a list and discard the operator. 
    3303            return convert_clauses[0] 
    3304        else: 
    3305            return None 
    3306 
    3307    @classmethod 
    3308    def _construct_raw( 
    3309        cls, 
    3310        operator: OperatorType, 
    3311        clauses: Optional[Sequence[ColumnElement[Any]]] = None, 
    3312    ) -> BooleanClauseList: 
    3313        self = cls.__new__(cls) 
    3314        self.clauses = tuple(clauses) if clauses else () 
    3315        self.group = True 
    3316        self.operator = operator 
    3317        self.type = type_api.BOOLEANTYPE 
    3318        self._is_implicitly_boolean = True 
    3319        return self 
    3320 
    3321    @classmethod 
    3322    def and_( 
    3323        cls, 
    3324        initial_clause: Union[ 
    3325            Literal[True], _ColumnExpressionArgument[bool], _NoArg 
    3326        ] = _NoArg.NO_ARG, 
    3327        *clauses: _ColumnExpressionArgument[bool], 
    3328    ) -> ColumnElement[bool]: 
    3329        r"""Produce a conjunction of expressions joined by ``AND``. 
    3330 
    3331        See :func:`_sql.and_` for full documentation. 
    3332        """ 
    3333        return cls._construct( 
    3334            operators.and_, 
    3335            True_._singleton, 
    3336            False_._singleton, 
    3337            initial_clause, 
    3338            *clauses, 
    3339        ) 
    3340 
    3341    @classmethod 
    3342    def or_( 
    3343        cls, 
    3344        initial_clause: Union[ 
    3345            Literal[False], _ColumnExpressionArgument[bool], _NoArg 
    3346        ] = _NoArg.NO_ARG, 
    3347        *clauses: _ColumnExpressionArgument[bool], 
    3348    ) -> ColumnElement[bool]: 
    3349        """Produce a conjunction of expressions joined by ``OR``. 
    3350 
    3351        See :func:`_sql.or_` for full documentation. 
    3352        """ 
    3353        return cls._construct( 
    3354            operators.or_, 
    3355            False_._singleton, 
    3356            True_._singleton, 
    3357            initial_clause, 
    3358            *clauses, 
    3359        ) 
    3360 
    3361    @property 
    3362    def _select_iterable(self) -> _SelectIterable: 
    3363        return (self,) 
    3364 
    3365    def self_group( 
    3366        self, against: Optional[OperatorType] = None 
    3367    ) -> Union[Self, Grouping[bool]]: 
    3368        if not self.clauses: 
    3369            return self 
    3370        else: 
    3371            return super().self_group(against=against) 
    3372 
    3373 
    3374and_ = BooleanClauseList.and_ 
    3375or_ = BooleanClauseList.or_ 
    3376 
    3377 
    3378class Tuple(ClauseList, ColumnElement[TupleAny]): 
    3379    """Represent a SQL tuple.""" 
    3380 
    3381    __visit_name__ = "tuple" 
    3382 
    3383    _traverse_internals: _TraverseInternalsType = ( 
    3384        ClauseList._traverse_internals + [] 
    3385    ) 
    3386 
    3387    type: TupleType 
    3388 
    3389    @util.preload_module("sqlalchemy.sql.sqltypes") 
    3390    def __init__( 
    3391        self, 
    3392        *clauses: _ColumnExpressionArgument[Any], 
    3393        types: Optional[Sequence[_TypeEngineArgument[Any]]] = None, 
    3394    ): 
    3395        sqltypes = util.preloaded.sql_sqltypes 
    3396 
    3397        if types is None: 
    3398            init_clauses: List[ColumnElement[Any]] = [ 
    3399                coercions.expect(roles.ExpressionElementRole, c) 
    3400                for c in clauses 
    3401            ] 
    3402        else: 
    3403            if len(types) != len(clauses): 
    3404                raise exc.ArgumentError( 
    3405                    "Wrong number of elements for %d-tuple: %r " 
    3406                    % (len(types), clauses) 
    3407                ) 
    3408            init_clauses = [ 
    3409                coercions.expect( 
    3410                    roles.ExpressionElementRole, 
    3411                    c, 
    3412                    type_=typ if not typ._isnull else None, 
    3413                ) 
    3414                for typ, c in zip(types, clauses) 
    3415            ] 
    3416 
    3417        self.type = sqltypes.TupleType(*[arg.type for arg in init_clauses]) 
    3418        super().__init__(*init_clauses) 
    3419 
    3420    @property 
    3421    def _select_iterable(self) -> _SelectIterable: 
    3422        return (self,) 
    3423 
    3424    def _bind_param(self, operator, obj, type_=None, expanding=False): 
    3425        if expanding: 
    3426            return BindParameter( 
    3427                None, 
    3428                value=obj, 
    3429                _compared_to_operator=operator, 
    3430                unique=True, 
    3431                expanding=True, 
    3432                type_=type_, 
    3433                _compared_to_type=self.type, 
    3434            ) 
    3435        else: 
    3436            return Tuple( 
    3437                *[ 
    3438                    BindParameter( 
    3439                        None, 
    3440                        o, 
    3441                        _compared_to_operator=operator, 
    3442                        _compared_to_type=compared_to_type, 
    3443                        unique=True, 
    3444                        type_=type_, 
    3445                    ) 
    3446                    for o, compared_to_type in zip(obj, self.type.types) 
    3447                ] 
    3448            ) 
    3449 
    3450    def self_group(self, against: Optional[OperatorType] = None) -> Self: 
    3451        # Tuple is parenthesized by definition. 
    3452        return self 
    3453 
    3454 
    3455class Case(ColumnElement[_T]): 
    3456    """Represent a ``CASE`` expression. 
    3457 
    3458    :class:`.Case` is produced using the :func:`.case` factory function, 
    3459    as in:: 
    3460 
    3461        from sqlalchemy import case 
    3462 
    3463        stmt = select(users_table).where( 
    3464            case( 
    3465                (users_table.c.name == "wendy", "W"), 
    3466                (users_table.c.name == "jack", "J"), 
    3467                else_="E", 
    3468            ) 
    3469        ) 
    3470 
    3471    Details on :class:`.Case` usage is at :func:`.case`. 
    3472 
    3473    .. seealso:: 
    3474 
    3475        :func:`.case` 
    3476 
    3477    """ 
    3478 
    3479    __visit_name__ = "case" 
    3480 
    3481    _traverse_internals: _TraverseInternalsType = [ 
    3482        ("value", InternalTraversal.dp_clauseelement), 
    3483        ("whens", InternalTraversal.dp_clauseelement_tuples), 
    3484        ("else_", InternalTraversal.dp_clauseelement), 
    3485    ] 
    3486 
    3487    # for case(), the type is derived from the whens.  so for the moment 
    3488    # users would have to cast() the case to get a specific type 
    3489 
    3490    whens: List[typing_Tuple[ColumnElement[bool], ColumnElement[_T]]] 
    3491    else_: Optional[ColumnElement[_T]] 
    3492    value: Optional[ColumnElement[Any]] 
    3493 
    3494    def __init__( 
    3495        self, 
    3496        *whens: Union[ 
    3497            typing_Tuple[_ColumnExpressionArgument[bool], Any], 
    3498            Mapping[Any, Any], 
    3499        ], 
    3500        value: Optional[Any] = None, 
    3501        else_: Optional[Any] = None, 
    3502    ): 
    3503        new_whens: Iterable[Any] = coercions._expression_collection_was_a_list( 
    3504            "whens", "case", whens 
    3505        ) 
    3506        try: 
    3507            new_whens = util.dictlike_iteritems(new_whens) 
    3508        except TypeError: 
    3509            pass 
    3510 
    3511        self.whens = [ 
    3512            ( 
    3513                coercions.expect( 
    3514                    roles.ExpressionElementRole, 
    3515                    c, 
    3516                    apply_propagate_attrs=self, 
    3517                ).self_group(), 
    3518                coercions.expect(roles.ExpressionElementRole, r), 
    3519            ) 
    3520            for (c, r) in new_whens 
    3521        ] 
    3522 
    3523        if value is None: 
    3524            self.value = None 
    3525        else: 
    3526            self.value = coercions.expect(roles.ExpressionElementRole, value) 
    3527 
    3528        if else_ is not None: 
    3529            self.else_ = coercions.expect(roles.ExpressionElementRole, else_) 
    3530        else: 
    3531            self.else_ = None 
    3532 
    3533        type_ = next( 
    3534            ( 
    3535                then.type 
    3536                # Iterate `whens` in reverse to match previous behaviour 
    3537                # where type of final element took priority 
    3538                for *_, then in reversed(self.whens) 
    3539                if not then.type._isnull 
    3540            ), 
    3541            self.else_.type if self.else_ is not None else type_api.NULLTYPE, 
    3542        ) 
    3543        self.type = cast(_T, type_) 
    3544 
    3545    @util.ro_non_memoized_property 
    3546    def _from_objects(self) -> List[FromClause]: 
    3547        return list( 
    3548            itertools.chain(*[x._from_objects for x in self.get_children()]) 
    3549        ) 
    3550 
    3551 
    3552class Cast(WrapsColumnExpression[_T]): 
    3553    """Represent a ``CAST`` expression. 
    3554 
    3555    :class:`.Cast` is produced using the :func:`.cast` factory function, 
    3556    as in:: 
    3557 
    3558        from sqlalchemy import cast, Numeric 
    3559 
    3560        stmt = select(cast(product_table.c.unit_price, Numeric(10, 4))) 
    3561 
    3562    Details on :class:`.Cast` usage is at :func:`.cast`. 
    3563 
    3564    .. seealso:: 
    3565 
    3566        :ref:`tutorial_casts` 
    3567 
    3568        :func:`.cast` 
    3569 
    3570        :func:`.try_cast` 
    3571 
    3572        :func:`.type_coerce` - an alternative to CAST that coerces the type 
    3573        on the Python side only, which is often sufficient to generate the 
    3574        correct SQL and data coercion. 
    3575 
    3576    """ 
    3577 
    3578    __visit_name__ = "cast" 
    3579 
    3580    _traverse_internals: _TraverseInternalsType = [ 
    3581        ("clause", InternalTraversal.dp_clauseelement), 
    3582        ("type", InternalTraversal.dp_type), 
    3583    ] 
    3584 
    3585    clause: ColumnElement[Any] 
    3586    type: TypeEngine[_T] 
    3587    typeclause: TypeClause 
    3588 
    3589    def __init__( 
    3590        self, 
    3591        expression: _ColumnExpressionArgument[Any], 
    3592        type_: _TypeEngineArgument[_T], 
    3593    ): 
    3594        self.type = type_api.to_instance(type_) 
    3595        self.clause = coercions.expect( 
    3596            roles.ExpressionElementRole, 
    3597            expression, 
    3598            type_=self.type, 
    3599            apply_propagate_attrs=self, 
    3600        ) 
    3601        self.typeclause = TypeClause(self.type) 
    3602 
    3603    @util.ro_non_memoized_property 
    3604    def _from_objects(self) -> List[FromClause]: 
    3605        return self.clause._from_objects 
    3606 
    3607    @property 
    3608    def wrapped_column_expression(self): 
    3609        return self.clause 
    3610 
    3611 
    3612class TryCast(Cast[_T]): 
    3613    """Represent a TRY_CAST expression. 
    3614 
    3615    Details on :class:`.TryCast` usage is at :func:`.try_cast`. 
    3616 
    3617    .. seealso:: 
    3618 
    3619        :func:`.try_cast` 
    3620 
    3621        :ref:`tutorial_casts` 
    3622    """ 
    3623 
    3624    __visit_name__ = "try_cast" 
    3625    inherit_cache = True 
    3626 
    3627 
    3628class TypeCoerce(WrapsColumnExpression[_T]): 
    3629    """Represent a Python-side type-coercion wrapper. 
    3630 
    3631    :class:`.TypeCoerce` supplies the :func:`_expression.type_coerce` 
    3632    function; see that function for usage details. 
    3633 
    3634    .. seealso:: 
    3635 
    3636        :func:`_expression.type_coerce` 
    3637 
    3638        :func:`.cast` 
    3639 
    3640    """ 
    3641 
    3642    __visit_name__ = "type_coerce" 
    3643 
    3644    _traverse_internals: _TraverseInternalsType = [ 
    3645        ("clause", InternalTraversal.dp_clauseelement), 
    3646        ("type", InternalTraversal.dp_type), 
    3647    ] 
    3648 
    3649    clause: ColumnElement[Any] 
    3650    type: TypeEngine[_T] 
    3651 
    3652    def __init__( 
    3653        self, 
    3654        expression: _ColumnExpressionArgument[Any], 
    3655        type_: _TypeEngineArgument[_T], 
    3656    ): 
    3657        self.type = type_api.to_instance(type_) 
    3658        self.clause = coercions.expect( 
    3659            roles.ExpressionElementRole, 
    3660            expression, 
    3661            type_=self.type, 
    3662            apply_propagate_attrs=self, 
    3663        ) 
    3664 
    3665    @util.ro_non_memoized_property 
    3666    def _from_objects(self) -> List[FromClause]: 
    3667        return self.clause._from_objects 
    3668 
    3669    @HasMemoized.memoized_attribute 
    3670    def typed_expression(self): 
    3671        if isinstance(self.clause, BindParameter): 
    3672            bp = self.clause._clone() 
    3673            bp.type = self.type 
    3674            return bp 
    3675        else: 
    3676            return self.clause 
    3677 
    3678    @property 
    3679    def wrapped_column_expression(self): 
    3680        return self.clause 
    3681 
    3682    def self_group( 
    3683        self, against: Optional[OperatorType] = None 
    3684    ) -> TypeCoerce[_T]: 
    3685        grouped = self.clause.self_group(against=against) 
    3686        if grouped is not self.clause: 
    3687            return TypeCoerce(grouped, self.type) 
    3688        else: 
    3689            return self 
    3690 
    3691 
    3692class Extract(ColumnElement[int]): 
    3693    """Represent a SQL EXTRACT clause, ``extract(field FROM expr)``.""" 
    3694 
    3695    __visit_name__ = "extract" 
    3696 
    3697    _traverse_internals: _TraverseInternalsType = [ 
    3698        ("expr", InternalTraversal.dp_clauseelement), 
    3699        ("field", InternalTraversal.dp_string), 
    3700    ] 
    3701 
    3702    expr: ColumnElement[Any] 
    3703    field: str 
    3704 
    3705    def __init__(self, field: str, expr: _ColumnExpressionArgument[Any]): 
    3706        self.type = type_api.INTEGERTYPE 
    3707        self.field = field 
    3708        self.expr = coercions.expect(roles.ExpressionElementRole, expr) 
    3709 
    3710    @util.ro_non_memoized_property 
    3711    def _from_objects(self) -> List[FromClause]: 
    3712        return self.expr._from_objects 
    3713 
    3714 
    3715class _label_reference(ColumnElement[_T]): 
    3716    """Wrap a column expression as it appears in a 'reference' context. 
    3717 
    3718    This expression is any that includes an _order_by_label_element, 
    3719    which is a Label, or a DESC / ASC construct wrapping a Label. 
    3720 
    3721    The production of _label_reference() should occur when an expression 
    3722    is added to this context; this includes the ORDER BY or GROUP BY of a 
    3723    SELECT statement, as well as a few other places, such as the ORDER BY 
    3724    within an OVER clause. 
    3725 
    3726    """ 
    3727 
    3728    __visit_name__ = "label_reference" 
    3729 
    3730    _traverse_internals: _TraverseInternalsType = [ 
    3731        ("element", InternalTraversal.dp_clauseelement) 
    3732    ] 
    3733 
    3734    element: ColumnElement[_T] 
    3735 
    3736    def __init__(self, element: ColumnElement[_T]): 
    3737        self.element = element 
    3738        self._propagate_attrs = element._propagate_attrs 
    3739 
    3740    @util.ro_non_memoized_property 
    3741    def _from_objects(self) -> List[FromClause]: 
    3742        return [] 
    3743 
    3744 
    3745class _textual_label_reference(ColumnElement[Any]): 
    3746    __visit_name__ = "textual_label_reference" 
    3747 
    3748    _traverse_internals: _TraverseInternalsType = [ 
    3749        ("element", InternalTraversal.dp_string) 
    3750    ] 
    3751 
    3752    def __init__(self, element: str): 
    3753        self.element = element 
    3754 
    3755    @util.memoized_property 
    3756    def _text_clause(self) -> TextClause: 
    3757        return TextClause(self.element) 
    3758 
    3759 
    3760class UnaryExpression(ColumnElement[_T]): 
    3761    """Define a 'unary' expression. 
    3762 
    3763    A unary expression has a single column expression 
    3764    and an operator.  The operator can be placed on the left 
    3765    (where it is called the 'operator') or right (where it is called the 
    3766    'modifier') of the column expression. 
    3767 
    3768    :class:`.UnaryExpression` is the basis for several unary operators 
    3769    including those used by :func:`.desc`, :func:`.asc`, :func:`.distinct`, 
    3770    :func:`.nulls_first` and :func:`.nulls_last`. 
    3771 
    3772    """ 
    3773 
    3774    __visit_name__ = "unary" 
    3775 
    3776    _traverse_internals: _TraverseInternalsType = [ 
    3777        ("element", InternalTraversal.dp_clauseelement), 
    3778        ("operator", InternalTraversal.dp_operator), 
    3779        ("modifier", InternalTraversal.dp_operator), 
    3780    ] 
    3781 
    3782    element: ColumnElement[Any] 
    3783    operator: Optional[OperatorType] 
    3784    modifier: Optional[OperatorType] 
    3785 
    3786    def __init__( 
    3787        self, 
    3788        element: ColumnElement[Any], 
    3789        *, 
    3790        operator: Optional[OperatorType] = None, 
    3791        modifier: Optional[OperatorType] = None, 
    3792        type_: Optional[_TypeEngineArgument[_T]] = None, 
    3793        wraps_column_expression: bool = False,  # legacy, not used as of 2.0.42 
    3794    ): 
    3795        self.operator = operator 
    3796        self.modifier = modifier 
    3797        self._propagate_attrs = element._propagate_attrs 
    3798        self.element = element.self_group( 
    3799            against=self.operator or self.modifier 
    3800        ) 
    3801 
    3802        # if type is None, we get NULLTYPE, which is our _T.  But I don't 
    3803        # know how to get the overloads to express that correctly 
    3804        self.type = type_api.to_instance(type_)  # type: ignore 
    3805 
    3806    def _wraps_unnamed_column(self): 
    3807        ungrouped = self.element._ungroup() 
    3808        return ( 
    3809            not isinstance(ungrouped, NamedColumn) 
    3810            or ungrouped._non_anon_label is None 
    3811        ) 
    3812 
    3813    @classmethod 
    3814    def _create_nulls_first( 
    3815        cls, 
    3816        column: _ColumnExpressionArgument[_T], 
    3817    ) -> UnaryExpression[_T]: 
    3818        return UnaryExpression( 
    3819            coercions.expect(roles.ByOfRole, column), 
    3820            modifier=operators.nulls_first_op, 
    3821        ) 
    3822 
    3823    @classmethod 
    3824    def _create_nulls_last( 
    3825        cls, 
    3826        column: _ColumnExpressionArgument[_T], 
    3827    ) -> UnaryExpression[_T]: 
    3828        return UnaryExpression( 
    3829            coercions.expect(roles.ByOfRole, column), 
    3830            modifier=operators.nulls_last_op, 
    3831        ) 
    3832 
    3833    @classmethod 
    3834    def _create_desc( 
    3835        cls, column: _ColumnExpressionOrStrLabelArgument[_T] 
    3836    ) -> UnaryExpression[_T]: 
    3837 
    3838        return UnaryExpression( 
    3839            coercions.expect(roles.ByOfRole, column), 
    3840            modifier=operators.desc_op, 
    3841        ) 
    3842 
    3843    @classmethod 
    3844    def _create_asc( 
    3845        cls, 
    3846        column: _ColumnExpressionOrStrLabelArgument[_T], 
    3847    ) -> UnaryExpression[_T]: 
    3848        return UnaryExpression( 
    3849            coercions.expect(roles.ByOfRole, column), 
    3850            modifier=operators.asc_op, 
    3851        ) 
    3852 
    3853    @classmethod 
    3854    def _create_distinct( 
    3855        cls, 
    3856        expr: _ColumnExpressionArgument[_T], 
    3857    ) -> UnaryExpression[_T]: 
    3858        col_expr: ColumnElement[_T] = coercions.expect( 
    3859            roles.ExpressionElementRole, expr 
    3860        ) 
    3861        return UnaryExpression( 
    3862            col_expr, 
    3863            operator=operators.distinct_op, 
    3864            type_=col_expr.type, 
    3865        ) 
    3866 
    3867    @classmethod 
    3868    def _create_bitwise_not( 
    3869        cls, 
    3870        expr: _ColumnExpressionArgument[_T], 
    3871    ) -> UnaryExpression[_T]: 
    3872        col_expr: ColumnElement[_T] = coercions.expect( 
    3873            roles.ExpressionElementRole, expr 
    3874        ) 
    3875        return UnaryExpression( 
    3876            col_expr, 
    3877            operator=operators.bitwise_not_op, 
    3878            type_=col_expr.type, 
    3879        ) 
    3880 
    3881    @property 
    3882    def _order_by_label_element(self) -> Optional[Label[Any]]: 
    3883        if operators.is_order_by_modifier(self.modifier): 
    3884            return self.element._order_by_label_element 
    3885        else: 
    3886            return None 
    3887 
    3888    @util.ro_non_memoized_property 
    3889    def _from_objects(self) -> List[FromClause]: 
    3890        return self.element._from_objects 
    3891 
    3892    def _negate(self) -> ColumnElement[Any]: 
    3893        if self.type._type_affinity is type_api.BOOLEANTYPE._type_affinity: 
    3894            return UnaryExpression( 
    3895                self.self_group(against=operators.inv), 
    3896                operator=operators.inv, 
    3897                type_=type_api.BOOLEANTYPE, 
    3898            ) 
    3899        else: 
    3900            return ColumnElement._negate(self) 
    3901 
    3902    def self_group( 
    3903        self, against: Optional[OperatorType] = None 
    3904    ) -> Union[Self, Grouping[_T]]: 
    3905        if self.operator and operators.is_precedent(self.operator, against): 
    3906            return Grouping(self) 
    3907        else: 
    3908            return self 
    3909 
    3910 
    3911class CollectionAggregate(UnaryExpression[_T]): 
    3912    """Forms the basis for right-hand collection operator modifiers 
    3913    ANY and ALL. 
    3914 
    3915    The ANY and ALL keywords are available in different ways on different 
    3916    backends.  On PostgreSQL, they only work for an ARRAY type.  On 
    3917    MySQL, they only work for subqueries. 
    3918 
    3919    """ 
    3920 
    3921    inherit_cache = True 
    3922    _is_collection_aggregate = True 
    3923 
    3924    @classmethod 
    3925    def _create_any( 
    3926        cls, expr: _ColumnExpressionArgument[_T] 
    3927    ) -> CollectionAggregate[bool]: 
    3928        """create CollectionAggregate for the legacy 
    3929        ARRAY.Comparator.any() method""" 
    3930        col_expr: ColumnElement[_T] = coercions.expect( 
    3931            roles.ExpressionElementRole, 
    3932            expr, 
    3933        ) 
    3934        col_expr = col_expr.self_group() 
    3935        return CollectionAggregate( 
    3936            col_expr, 
    3937            operator=operators.any_op, 
    3938            type_=type_api.BOOLEANTYPE, 
    3939        ) 
    3940 
    3941    @classmethod 
    3942    def _create_all( 
    3943        cls, expr: _ColumnExpressionArgument[_T] 
    3944    ) -> CollectionAggregate[bool]: 
    3945        """create CollectionAggregate for the legacy 
    3946        ARRAY.Comparator.all() method""" 
    3947        col_expr: ColumnElement[_T] = coercions.expect( 
    3948            roles.ExpressionElementRole, 
    3949            expr, 
    3950        ) 
    3951        col_expr = col_expr.self_group() 
    3952        return CollectionAggregate( 
    3953            col_expr, 
    3954            operator=operators.all_op, 
    3955            type_=type_api.BOOLEANTYPE, 
    3956        ) 
    3957 
    3958    @util.preload_module("sqlalchemy.sql.sqltypes") 
    3959    def _bind_param( 
    3960        self, 
    3961        operator: operators.OperatorType, 
    3962        obj: Any, 
    3963        type_: Optional[TypeEngine[_T]] = None, 
    3964        expanding: bool = False, 
    3965    ) -> BindParameter[_T]: 
    3966        """For new style any_(), all_(), ensure compared literal value 
    3967        receives appropriate bound parameter type.""" 
    3968 
    3969        # a CollectionAggregate is specific to ARRAY or int 
    3970        # only.  So for ARRAY case, make sure we use correct element type 
    3971        sqltypes = util.preloaded.sql_sqltypes 
    3972        if self.element.type._type_affinity is sqltypes.ARRAY: 
    3973            compared_to_type = cast( 
    3974                sqltypes.ARRAY[Any], self.element.type 
    3975            ).item_type 
    3976        else: 
    3977            compared_to_type = self.element.type 
    3978 
    3979        return BindParameter( 
    3980            None, 
    3981            obj, 
    3982            _compared_to_operator=operator, 
    3983            type_=type_, 
    3984            _compared_to_type=compared_to_type, 
    3985            unique=True, 
    3986            expanding=expanding, 
    3987        ) 
    3988 
    3989    # operate and reverse_operate are hardwired to 
    3990    # dispatch onto the type comparator directly, so that we can 
    3991    # ensure "reversed" behavior. 
    3992    def operate( 
    3993        self, op: OperatorType, *other: Any, **kwargs: Any 
    3994    ) -> ColumnElement[_T]: 
    3995        if not operators.is_comparison(op): 
    3996            raise exc.ArgumentError( 
    3997                "Only comparison operators may be used with ANY/ALL" 
    3998            ) 
    3999        kwargs["reverse"] = True 
    4000        return self.comparator.operate(operators.mirror(op), *other, **kwargs) 
    4001 
    4002    def reverse_operate( 
    4003        self, op: OperatorType, other: Any, **kwargs: Any 
    4004    ) -> ColumnElement[_T]: 
    4005        # comparison operators should never call reverse_operate 
    4006        assert not operators.is_comparison(op) 
    4007        raise exc.ArgumentError( 
    4008            "Only comparison operators may be used with ANY/ALL" 
    4009        ) 
    4010 
    4011 
    4012class AsBoolean(WrapsColumnExpression[bool], UnaryExpression[bool]): 
    4013    inherit_cache = True 
    4014 
    4015    def __init__(self, element, operator, negate): 
    4016        self.element = element 
    4017        self.type = type_api.BOOLEANTYPE 
    4018        self.operator = operator 
    4019        self.negate = negate 
    4020        self.modifier = None 
    4021        self._is_implicitly_boolean = element._is_implicitly_boolean 
    4022 
    4023    @property 
    4024    def wrapped_column_expression(self): 
    4025        return self.element 
    4026 
    4027    def self_group(self, against: Optional[OperatorType] = None) -> Self: 
    4028        return self 
    4029 
    4030    def _negate(self): 
    4031        if isinstance(self.element, (True_, False_)): 
    4032            return self.element._negate() 
    4033        else: 
    4034            return AsBoolean(self.element, self.negate, self.operator) 
    4035 
    4036 
    4037class BinaryExpression(OperatorExpression[_T]): 
    4038    """Represent an expression that is ``LEFT <operator> RIGHT``. 
    4039 
    4040    A :class:`.BinaryExpression` is generated automatically 
    4041    whenever two column expressions are used in a Python binary expression: 
    4042 
    4043    .. sourcecode:: pycon+sql 
    4044 
    4045        >>> from sqlalchemy.sql import column 
    4046        >>> column("a") + column("b") 
    4047        <sqlalchemy.sql.expression.BinaryExpression object at 0x101029dd0> 
    4048        >>> print(column("a") + column("b")) 
    4049        {printsql}a + b 
    4050 
    4051    """ 
    4052 
    4053    __visit_name__ = "binary" 
    4054 
    4055    _traverse_internals: _TraverseInternalsType = [ 
    4056        ("left", InternalTraversal.dp_clauseelement), 
    4057        ("right", InternalTraversal.dp_clauseelement), 
    4058        ("operator", InternalTraversal.dp_operator), 
    4059        ("negate", InternalTraversal.dp_operator), 
    4060        ("modifiers", InternalTraversal.dp_plain_dict), 
    4061        ( 
    4062            "type", 
    4063            InternalTraversal.dp_type, 
    4064        ), 
    4065    ] 
    4066 
    4067    _cache_key_traversal = [ 
    4068        ("left", InternalTraversal.dp_clauseelement), 
    4069        ("right", InternalTraversal.dp_clauseelement), 
    4070        ("operator", InternalTraversal.dp_operator), 
    4071        ("modifiers", InternalTraversal.dp_plain_dict), 
    4072        # "type" affects JSON CAST operators, so while redundant in most cases, 
    4073        # is needed for that one 
    4074        ( 
    4075            "type", 
    4076            InternalTraversal.dp_type, 
    4077        ), 
    4078    ] 
    4079 
    4080    _is_implicitly_boolean = True 
    4081    """Indicates that any database will know this is a boolean expression 
    4082    even if the database does not have an explicit boolean datatype. 
    4083 
    4084    """ 
    4085 
    4086    left: ColumnElement[Any] 
    4087    right: ColumnElement[Any] 
    4088    modifiers: Mapping[str, Any] 
    4089 
    4090    def __init__( 
    4091        self, 
    4092        left: ColumnElement[Any], 
    4093        right: ColumnElement[Any], 
    4094        operator: OperatorType, 
    4095        type_: Optional[_TypeEngineArgument[_T]] = None, 
    4096        negate: Optional[OperatorType] = None, 
    4097        modifiers: Optional[Mapping[str, Any]] = None, 
    4098    ): 
    4099        # allow compatibility with libraries that 
    4100        # refer to BinaryExpression directly and pass strings 
    4101        if isinstance(operator, str): 
    4102            operator = operators.custom_op(operator) 
    4103        self._orig = (left.__hash__(), right.__hash__()) 
    4104        self._propagate_attrs = left._propagate_attrs or right._propagate_attrs 
    4105        self.left = left.self_group(against=operator) 
    4106        self.right = right.self_group(against=operator) 
    4107        self.operator = operator 
    4108 
    4109        # if type is None, we get NULLTYPE, which is our _T.  But I don't 
    4110        # know how to get the overloads to express that correctly 
    4111        self.type = type_api.to_instance(type_)  # type: ignore 
    4112 
    4113        self.negate = negate 
    4114        self._is_implicitly_boolean = operators.is_boolean(operator) 
    4115 
    4116        if modifiers is None: 
    4117            self.modifiers = {} 
    4118        else: 
    4119            self.modifiers = modifiers 
    4120 
    4121    @property 
    4122    def _flattened_operator_clauses( 
    4123        self, 
    4124    ) -> typing_Tuple[ColumnElement[Any], ...]: 
    4125        return (self.left, self.right) 
    4126 
    4127    def __bool__(self): 
    4128        """Implement Python-side "bool" for BinaryExpression as a 
    4129        simple "identity" check for the left and right attributes, 
    4130        if the operator is "eq" or "ne".  Otherwise the expression 
    4131        continues to not support "bool" like all other column expressions. 
    4132 
    4133        The rationale here is so that ColumnElement objects can be hashable. 
    4134        What?  Well, suppose you do this:: 
    4135 
    4136            c1, c2 = column("x"), column("y") 
    4137            s1 = set([c1, c2]) 
    4138 
    4139        We do that **a lot**, columns inside of sets is an extremely basic 
    4140        thing all over the ORM for example. 
    4141 
    4142        So what happens if we do this? :: 
    4143 
    4144            c1 in s1 
    4145 
    4146        Hashing means it will normally use ``__hash__()`` of the object, 
    4147        but in case of hash collision, it's going to also do ``c1 == c1`` 
    4148        and/or ``c1 == c2`` inside.  Those operations need to return a 
    4149        True/False value.   But because we override ``==`` and ``!=``, they're 
    4150        going to get a BinaryExpression.  Hence we implement ``__bool__`` here 
    4151        so that these comparisons behave in this particular context mostly 
    4152        like regular object comparisons.  Thankfully Python is OK with 
    4153        that!  Otherwise we'd have to use special set classes for columns 
    4154        (which we used to do, decades ago). 
    4155 
    4156        """ 
    4157        if self.operator in (operators.eq, operators.ne): 
    4158            # this is using the eq/ne operator given int hash values, 
    4159            # rather than Operator, so that "bool" can be based on 
    4160            # identity 
    4161            return self.operator(*self._orig)  # type: ignore 
    4162        else: 
    4163            raise TypeError("Boolean value of this clause is not defined") 
    4164 
    4165    if typing.TYPE_CHECKING: 
    4166 
    4167        def __invert__( 
    4168            self: BinaryExpression[_T], 
    4169        ) -> BinaryExpression[_T]: ... 
    4170 
    4171    @util.ro_non_memoized_property 
    4172    def _from_objects(self) -> List[FromClause]: 
    4173        return self.left._from_objects + self.right._from_objects 
    4174 
    4175    def _negate(self): 
    4176        if self.negate is not None: 
    4177            return BinaryExpression( 
    4178                self.left, 
    4179                self.right._negate_in_binary(self.negate, self.operator), 
    4180                self.negate, 
    4181                negate=self.operator, 
    4182                type_=self.type, 
    4183                modifiers=self.modifiers, 
    4184            ) 
    4185        else: 
    4186            return self.self_group()._negate() 
    4187 
    4188 
    4189class Slice(ColumnElement[Any]): 
    4190    """Represent SQL for a Python array-slice object. 
    4191 
    4192    This is not a specific SQL construct at this level, but 
    4193    may be interpreted by specific dialects, e.g. PostgreSQL. 
    4194 
    4195    """ 
    4196 
    4197    __visit_name__ = "slice" 
    4198 
    4199    _traverse_internals: _TraverseInternalsType = [ 
    4200        ("start", InternalTraversal.dp_clauseelement), 
    4201        ("stop", InternalTraversal.dp_clauseelement), 
    4202        ("step", InternalTraversal.dp_clauseelement), 
    4203    ] 
    4204 
    4205    def __init__(self, start, stop, step, _name=None): 
    4206        self.start = coercions.expect( 
    4207            roles.ExpressionElementRole, 
    4208            start, 
    4209            name=_name, 
    4210            type_=type_api.INTEGERTYPE, 
    4211        ) 
    4212        self.stop = coercions.expect( 
    4213            roles.ExpressionElementRole, 
    4214            stop, 
    4215            name=_name, 
    4216            type_=type_api.INTEGERTYPE, 
    4217        ) 
    4218        self.step = coercions.expect( 
    4219            roles.ExpressionElementRole, 
    4220            step, 
    4221            name=_name, 
    4222            type_=type_api.INTEGERTYPE, 
    4223        ) 
    4224        self.type = type_api.NULLTYPE 
    4225 
    4226    def self_group(self, against: Optional[OperatorType] = None) -> Self: 
    4227        assert against is operator.getitem 
    4228        return self 
    4229 
    4230 
    4231class IndexExpression(BinaryExpression[Any]): 
    4232    """Represent the class of expressions that are like an "index" 
    4233    operation.""" 
    4234 
    4235    inherit_cache = True 
    4236 
    4237 
    4238class GroupedElement(DQLDMLClauseElement): 
    4239    """Represent any parenthesized expression""" 
    4240 
    4241    __visit_name__ = "grouping" 
    4242 
    4243    def self_group(self, against: Optional[OperatorType] = None) -> Self: 
    4244        return self 
    4245 
    4246    def _ungroup(self) -> ClauseElement: 
    4247        raise NotImplementedError() 
    4248 
    4249 
    4250class Grouping(GroupedElement, ColumnElement[_T]): 
    4251    """Represent a grouping within a column expression""" 
    4252 
    4253    _traverse_internals: _TraverseInternalsType = [ 
    4254        ("element", InternalTraversal.dp_clauseelement), 
    4255        ("type", InternalTraversal.dp_type), 
    4256    ] 
    4257 
    4258    _cache_key_traversal = [ 
    4259        ("element", InternalTraversal.dp_clauseelement), 
    4260    ] 
    4261 
    4262    element: Union[ 
    4263        TextClause, ClauseList, ColumnElement[_T], CompilerColumnElement 
    4264    ] 
    4265 
    4266    def __init__( 
    4267        self, 
    4268        element: Union[ 
    4269            TextClause, ClauseList, ColumnElement[_T], CompilerColumnElement 
    4270        ], 
    4271    ): 
    4272        self.element = element 
    4273 
    4274        # nulltype assignment issue 
    4275        self.type = getattr(element, "type", type_api.NULLTYPE)  # type: ignore 
    4276        self._propagate_attrs = element._propagate_attrs 
    4277 
    4278    def _with_binary_element_type(self, type_): 
    4279        return self.__class__(self.element._with_binary_element_type(type_)) 
    4280 
    4281    def _ungroup(self) -> ColumnElement[_T]: 
    4282        assert isinstance(self.element, ColumnElement) 
    4283        return self.element._ungroup() 
    4284 
    4285    @util.memoized_property 
    4286    def _is_implicitly_boolean(self): 
    4287        return self.element._is_implicitly_boolean 
    4288 
    4289    @util.non_memoized_property 
    4290    def _tq_label(self) -> Optional[str]: 
    4291        return ( 
    4292            getattr(self.element, "_tq_label", None) or self._anon_name_label 
    4293        ) 
    4294 
    4295    @util.non_memoized_property 
    4296    def _proxies(self) -> List[ColumnElement[Any]]: 
    4297        if isinstance(self.element, ColumnElement): 
    4298            return [self.element] 
    4299        else: 
    4300            return [] 
    4301 
    4302    @util.ro_non_memoized_property 
    4303    def _from_objects(self) -> List[FromClause]: 
    4304        return self.element._from_objects 
    4305 
    4306    def __getattr__(self, attr): 
    4307        return getattr(self.element, attr) 
    4308 
    4309    def __getstate__(self): 
    4310        return {"element": self.element, "type": self.type} 
    4311 
    4312    def __setstate__(self, state): 
    4313        self.element = state["element"] 
    4314        self.type = state["type"] 
    4315 
    4316    if TYPE_CHECKING: 
    4317 
    4318        def self_group( 
    4319            self, against: Optional[OperatorType] = None 
    4320        ) -> Self: ... 
    4321 
    4322 
    4323class _OverrideBinds(Grouping[_T]): 
    4324    """used by cache_key->_apply_params_to_element to allow compilation / 
    4325    execution of a SQL element that's been cached, using an alternate set of 
    4326    bound parameter values. 
    4327 
    4328    This is used by the ORM to swap new parameter values into expressions 
    4329    that are embedded into loader options like with_expression(), 
    4330    selectinload().  Previously, this task was accomplished using the 
    4331    .params() method which would perform a deep-copy instead.  This deep 
    4332    copy proved to be too expensive for more complex expressions. 
    4333 
    4334    See #11085 
    4335 
    4336    """ 
    4337 
    4338    __visit_name__ = "override_binds" 
    4339 
    4340    def __init__( 
    4341        self, 
    4342        element: ColumnElement[_T], 
    4343        bindparams: Sequence[BindParameter[Any]], 
    4344        replaces_params: Sequence[BindParameter[Any]], 
    4345    ): 
    4346        self.element = element 
    4347        self.translate = { 
    4348            k.key: v.value for k, v in zip(replaces_params, bindparams) 
    4349        } 
    4350 
    4351    def _gen_cache_key( 
    4352        self, anon_map: anon_map, bindparams: List[BindParameter[Any]] 
    4353    ) -> Optional[typing_Tuple[Any, ...]]: 
    4354        """generate a cache key for the given element, substituting its bind 
    4355        values for the translation values present.""" 
    4356 
    4357        existing_bps: List[BindParameter[Any]] = [] 
    4358        ck = self.element._gen_cache_key(anon_map, existing_bps) 
    4359 
    4360        bindparams.extend( 
    4361            ( 
    4362                bp._with_value( 
    4363                    self.translate[bp.key], maintain_key=True, required=False 
    4364                ) 
    4365                if bp.key in self.translate 
    4366                else bp 
    4367            ) 
    4368            for bp in existing_bps 
    4369        ) 
    4370 
    4371        return ck 
    4372 
    4373 
    4374class Over(ColumnElement[_T]): 
    4375    """Represent an OVER clause. 
    4376 
    4377    This is a special operator against a so-called 
    4378    "window" function, as well as any aggregate function, 
    4379    which produces results relative to the result set 
    4380    itself.  Most modern SQL backends now support window functions. 
    4381 
    4382    """ 
    4383 
    4384    __visit_name__ = "over" 
    4385 
    4386    _traverse_internals: _TraverseInternalsType = [ 
    4387        ("element", InternalTraversal.dp_clauseelement), 
    4388        ("order_by", InternalTraversal.dp_clauseelement), 
    4389        ("partition_by", InternalTraversal.dp_clauseelement), 
    4390        ("range_", InternalTraversal.dp_clauseelement), 
    4391        ("rows", InternalTraversal.dp_clauseelement), 
    4392        ("groups", InternalTraversal.dp_clauseelement), 
    4393    ] 
    4394 
    4395    order_by: Optional[ClauseList] = None 
    4396    partition_by: Optional[ClauseList] = None 
    4397 
    4398    element: ColumnElement[_T] 
    4399    """The underlying expression object to which this :class:`.Over` 
    4400    object refers.""" 
    4401 
    4402    range_: Optional[_FrameClause] 
    4403    rows: Optional[_FrameClause] 
    4404    groups: Optional[_FrameClause] 
    4405 
    4406    def __init__( 
    4407        self, 
    4408        element: ColumnElement[_T], 
    4409        partition_by: Optional[_ByArgument] = None, 
    4410        order_by: Optional[_ByArgument] = None, 
    4411        range_: Optional[typing_Tuple[Optional[int], Optional[int]]] = None, 
    4412        rows: Optional[typing_Tuple[Optional[int], Optional[int]]] = None, 
    4413        groups: Optional[typing_Tuple[Optional[int], Optional[int]]] = None, 
    4414    ): 
    4415        self.element = element 
    4416        if order_by is not None: 
    4417            self.order_by = ClauseList( 
    4418                *util.to_list(order_by), _literal_as_text_role=roles.ByOfRole 
    4419            ) 
    4420        if partition_by is not None: 
    4421            self.partition_by = ClauseList( 
    4422                *util.to_list(partition_by), 
    4423                _literal_as_text_role=roles.ByOfRole, 
    4424            ) 
    4425 
    4426        if sum(bool(item) for item in (range_, rows, groups)) > 1: 
    4427            raise exc.ArgumentError( 
    4428                "only one of 'rows', 'range_', or 'groups' may be provided" 
    4429            ) 
    4430        else: 
    4431            self.range_ = _FrameClause(range_) if range_ else None 
    4432            self.rows = _FrameClause(rows) if rows else None 
    4433            self.groups = _FrameClause(groups) if groups else None 
    4434 
    4435    if not TYPE_CHECKING: 
    4436 
    4437        @util.memoized_property 
    4438        def type(self) -> TypeEngine[_T]:  # noqa: A001 
    4439            return self.element.type 
    4440 
    4441    @util.ro_non_memoized_property 
    4442    def _from_objects(self) -> List[FromClause]: 
    4443        return list( 
    4444            itertools.chain( 
    4445                *[ 
    4446                    c._from_objects 
    4447                    for c in (self.element, self.partition_by, self.order_by) 
    4448                    if c is not None 
    4449                ] 
    4450            ) 
    4451        ) 
    4452 
    4453 
    4454class _FrameClauseType(Enum): 
    4455    RANGE_UNBOUNDED = 0 
    4456    RANGE_CURRENT = 1 
    4457    RANGE_PRECEDING = 2 
    4458    RANGE_FOLLOWING = 3 
    4459 
    4460 
    4461class _FrameClause(ClauseElement): 
    4462    """indicate the 'rows' or 'range' field of a window function, e.g. using 
    4463    :class:`.Over`. 
    4464 
    4465    .. versionadded:: 2.1 
    4466 
    4467    """ 
    4468 
    4469    __visit_name__ = "frame_clause" 
    4470 
    4471    _traverse_internals: _TraverseInternalsType = [ 
    4472        ("lower_integer_bind", InternalTraversal.dp_clauseelement), 
    4473        ("upper_integer_bind", InternalTraversal.dp_clauseelement), 
    4474        ("lower_type", InternalTraversal.dp_plain_obj), 
    4475        ("upper_type", InternalTraversal.dp_plain_obj), 
    4476    ] 
    4477 
    4478    def __init__( 
    4479        self, 
    4480        range_: typing_Tuple[Optional[int], Optional[int]], 
    4481    ): 
    4482        try: 
    4483            r0, r1 = range_ 
    4484        except (ValueError, TypeError) as ve: 
    4485            raise exc.ArgumentError("2-tuple expected for range/rows") from ve 
    4486 
    4487        if r0 is None: 
    4488            self.lower_type = _FrameClauseType.RANGE_UNBOUNDED 
    4489            self.lower_integer_bind = None 
    4490        else: 
    4491            try: 
    4492                lower_integer = int(r0) 
    4493            except ValueError as err: 
    4494                raise exc.ArgumentError( 
    4495                    "Integer or None expected for range value" 
    4496                ) from err 
    4497            else: 
    4498                if lower_integer == 0: 
    4499                    self.lower_type = _FrameClauseType.RANGE_CURRENT 
    4500                    self.lower_integer_bind = None 
    4501                elif lower_integer < 0: 
    4502                    self.lower_type = _FrameClauseType.RANGE_PRECEDING 
    4503                    self.lower_integer_bind = literal( 
    4504                        abs(lower_integer), type_api.INTEGERTYPE 
    4505                    ) 
    4506                else: 
    4507                    self.lower_type = _FrameClauseType.RANGE_FOLLOWING 
    4508                    self.lower_integer_bind = literal( 
    4509                        lower_integer, type_api.INTEGERTYPE 
    4510                    ) 
    4511 
    4512        if r1 is None: 
    4513            self.upper_type = _FrameClauseType.RANGE_UNBOUNDED 
    4514            self.upper_integer_bind = None 
    4515        else: 
    4516            try: 
    4517                upper_integer = int(r1) 
    4518            except ValueError as err: 
    4519                raise exc.ArgumentError( 
    4520                    "Integer or None expected for range value" 
    4521                ) from err 
    4522            else: 
    4523                if upper_integer == 0: 
    4524                    self.upper_type = _FrameClauseType.RANGE_CURRENT 
    4525                    self.upper_integer_bind = None 
    4526                elif upper_integer < 0: 
    4527                    self.upper_type = _FrameClauseType.RANGE_PRECEDING 
    4528                    self.upper_integer_bind = literal( 
    4529                        abs(upper_integer), type_api.INTEGERTYPE 
    4530                    ) 
    4531                else: 
    4532                    self.upper_type = _FrameClauseType.RANGE_FOLLOWING 
    4533                    self.upper_integer_bind = literal( 
    4534                        upper_integer, type_api.INTEGERTYPE 
    4535                    ) 
    4536 
    4537 
    4538class AggregateOrderBy(WrapsColumnExpression[_T]): 
    4539    """Represent an aggregate ORDER BY expression. 
    4540 
    4541    This is a special operator against aggregate functions such as 
    4542    ``array_agg()``, ``json_arrayagg()`` ``string_agg()``, etc. that provides 
    4543    for an ORDER BY expression, using a syntax that's compatible with 
    4544    the backend. 
    4545 
    4546    :class:`.AggregateOrderBy` is a generalized version of the 
    4547    :class:`.WithinGroup` construct, the latter of which always provides a 
    4548    "WITHIN GROUP (ORDER BY ...)" expression. :class:`.AggregateOrderBy` will 
    4549    also compile to "WITHIN GROUP (ORDER BY ...)" on backends such as Oracle 
    4550    and SQL Server that don't have another style of aggregate function 
    4551    ordering. 
    4552 
    4553    .. versionadded:: 2.1 
    4554 
    4555 
    4556    """ 
    4557 
    4558    __visit_name__ = "aggregateorderby" 
    4559 
    4560    _traverse_internals: _TraverseInternalsType = [ 
    4561        ("element", InternalTraversal.dp_clauseelement), 
    4562        ("order_by", InternalTraversal.dp_clauseelement), 
    4563    ] 
    4564 
    4565    order_by: ClauseList 
    4566 
    4567    def __init__( 
    4568        self, 
    4569        element: Union[FunctionElement[_T], FunctionFilter[_T]], 
    4570        *order_by: _ColumnExpressionArgument[Any], 
    4571    ): 
    4572        self.element = element 
    4573        if not order_by: 
    4574            raise TypeError("at least one ORDER BY element is required") 
    4575        self.order_by = ClauseList( 
    4576            *util.to_list(order_by), _literal_as_text_role=roles.ByOfRole 
    4577        ) 
    4578 
    4579    if not TYPE_CHECKING: 
    4580 
    4581        @util.memoized_property 
    4582        def type(self) -> TypeEngine[_T]:  # noqa: A001 
    4583            return self.element.type 
    4584 
    4585    @property 
    4586    def wrapped_column_expression(self) -> ColumnElement[_T]: 
    4587        return self.element 
    4588 
    4589    def __reduce__(self): 
    4590        return self.__class__, (self.element,) + ( 
    4591            tuple(self.order_by) if self.order_by is not None else () 
    4592        ) 
    4593 
    4594    def over( 
    4595        self, 
    4596        *, 
    4597        partition_by: Optional[_ByArgument] = None, 
    4598        order_by: Optional[_ByArgument] = None, 
    4599        rows: Optional[typing_Tuple[Optional[int], Optional[int]]] = None, 
    4600        range_: Optional[typing_Tuple[Optional[int], Optional[int]]] = None, 
    4601        groups: Optional[typing_Tuple[Optional[int], Optional[int]]] = None, 
    4602    ) -> Over[_T]: 
    4603        """Produce an OVER clause against this :class:`.WithinGroup` 
    4604        construct. 
    4605 
    4606        This function has the same signature as that of 
    4607        :meth:`.FunctionElement.over`. 
    4608 
    4609        """ 
    4610        return Over( 
    4611            self, 
    4612            partition_by=partition_by, 
    4613            order_by=order_by, 
    4614            range_=range_, 
    4615            rows=rows, 
    4616            groups=groups, 
    4617        ) 
    4618 
    4619    @overload 
    4620    def filter(self) -> Self: ... 
    4621 
    4622    @overload 
    4623    def filter( 
    4624        self, 
    4625        __criterion0: _ColumnExpressionArgument[bool], 
    4626        *criterion: _ColumnExpressionArgument[bool], 
    4627    ) -> FunctionFilter[_T]: ... 
    4628 
    4629    def filter( 
    4630        self, *criterion: _ColumnExpressionArgument[bool] 
    4631    ) -> Union[Self, FunctionFilter[_T]]: 
    4632        """Produce a FILTER clause against this function.""" 
    4633        if not criterion: 
    4634            return self 
    4635        return FunctionFilter(self, *criterion) 
    4636 
    4637    @util.ro_non_memoized_property 
    4638    def _from_objects(self) -> List[FromClause]: 
    4639        return list( 
    4640            itertools.chain( 
    4641                *[ 
    4642                    c._from_objects 
    4643                    for c in (self.element, self.order_by) 
    4644                    if c is not None 
    4645                ] 
    4646            ) 
    4647        ) 
    4648 
    4649 
    4650class WithinGroup(AggregateOrderBy[_T]): 
    4651    """Represent a WITHIN GROUP (ORDER BY) clause. 
    4652 
    4653    This is a special operator against so-called 
    4654    "ordered set aggregate" and "hypothetical 
    4655    set aggregate" functions, including ``percentile_cont()``, 
    4656    ``rank()``, ``dense_rank()``, etc. 
    4657 
    4658    It's supported only by certain database backends, such as PostgreSQL, 
    4659    Oracle Database and MS SQL Server. 
    4660 
    4661    The :class:`.WithinGroup` construct extracts its type from the 
    4662    method :meth:`.FunctionElement.within_group_type`.  If this returns 
    4663    ``None``, the function's ``.type`` is used. 
    4664 
    4665    """ 
    4666 
    4667    __visit_name__ = "withingroup" 
    4668    inherit_cache = True 
    4669 
    4670    if not TYPE_CHECKING: 
    4671 
    4672        @util.memoized_property 
    4673        def type(self) -> TypeEngine[_T]:  # noqa: A001 
    4674            wgt = self.element.within_group_type(self) 
    4675            if wgt is not None: 
    4676                return wgt 
    4677            else: 
    4678                return self.element.type 
    4679 
    4680 
    4681class FunctionFilter(Generative, ColumnElement[_T]): 
    4682    """Represent a function FILTER clause. 
    4683 
    4684    This is a special operator against aggregate and window functions, 
    4685    which controls which rows are passed to it. 
    4686    It's supported only by certain database backends. 
    4687 
    4688    Invocation of :class:`.FunctionFilter` is via 
    4689    :meth:`.FunctionElement.filter`:: 
    4690 
    4691        func.count(1).filter(True) 
    4692 
    4693    .. seealso:: 
    4694 
    4695        :meth:`.FunctionElement.filter` 
    4696 
    4697    """ 
    4698 
    4699    __visit_name__ = "funcfilter" 
    4700 
    4701    _traverse_internals: _TraverseInternalsType = [ 
    4702        ("func", InternalTraversal.dp_clauseelement), 
    4703        ("criterion", InternalTraversal.dp_clauseelement), 
    4704    ] 
    4705 
    4706    criterion: Optional[ColumnElement[bool]] = None 
    4707 
    4708    def __init__( 
    4709        self, 
    4710        func: Union[FunctionElement[_T], AggregateOrderBy[_T]], 
    4711        *criterion: _ColumnExpressionArgument[bool], 
    4712    ): 
    4713        self.func = func 
    4714        self.filter.non_generative(self, *criterion)  # type: ignore 
    4715 
    4716    @_generative 
    4717    def filter(self, *criterion: _ColumnExpressionArgument[bool]) -> Self: 
    4718        """Produce an additional FILTER against the function. 
    4719 
    4720        This method adds additional criteria to the initial criteria 
    4721        set up by :meth:`.FunctionElement.filter`. 
    4722 
    4723        Multiple criteria are joined together at SQL render time 
    4724        via ``AND``. 
    4725 
    4726 
    4727        """ 
    4728 
    4729        for crit in list(criterion): 
    4730            crit = coercions.expect(roles.WhereHavingRole, crit) 
    4731 
    4732            if self.criterion is not None: 
    4733                self.criterion = self.criterion & crit 
    4734            else: 
    4735                self.criterion = crit 
    4736 
    4737        return self 
    4738 
    4739    def over( 
    4740        self, 
    4741        partition_by: Optional[ 
    4742            Union[ 
    4743                Iterable[_ColumnExpressionArgument[Any]], 
    4744                _ColumnExpressionArgument[Any], 
    4745            ] 
    4746        ] = None, 
    4747        order_by: Optional[ 
    4748            Union[ 
    4749                Iterable[_ColumnExpressionArgument[Any]], 
    4750                _ColumnExpressionArgument[Any], 
    4751            ] 
    4752        ] = None, 
    4753        range_: Optional[typing_Tuple[Optional[int], Optional[int]]] = None, 
    4754        rows: Optional[typing_Tuple[Optional[int], Optional[int]]] = None, 
    4755        groups: Optional[typing_Tuple[Optional[int], Optional[int]]] = None, 
    4756    ) -> Over[_T]: 
    4757        """Produce an OVER clause against this filtered function. 
    4758 
    4759        Used against aggregate or so-called "window" functions, 
    4760        for database backends that support window functions. 
    4761 
    4762        The expression:: 
    4763 
    4764            func.rank().filter(MyClass.y > 5).over(order_by="x") 
    4765 
    4766        is shorthand for:: 
    4767 
    4768            from sqlalchemy import over, funcfilter 
    4769 
    4770            over(funcfilter(func.rank(), MyClass.y > 5), order_by="x") 
    4771 
    4772        See :func:`_expression.over` for a full description. 
    4773 
    4774        """ 
    4775        return Over( 
    4776            self, 
    4777            partition_by=partition_by, 
    4778            order_by=order_by, 
    4779            range_=range_, 
    4780            rows=rows, 
    4781            groups=groups, 
    4782        ) 
    4783 
    4784    def within_group( 
    4785        self, *order_by: _ColumnExpressionArgument[Any] 
    4786    ) -> WithinGroup[_T]: 
    4787        """Produce a WITHIN GROUP (ORDER BY expr) clause against 
    4788        this function. 
    4789        """ 
    4790        return WithinGroup(self, *order_by) 
    4791 
    4792    def within_group_type( 
    4793        self, within_group: WithinGroup[_T] 
    4794    ) -> Optional[TypeEngine[_T]]: 
    4795        return None 
    4796 
    4797    def self_group( 
    4798        self, against: Optional[OperatorType] = None 
    4799    ) -> Union[Self, Grouping[_T]]: 
    4800        if operators.is_precedent(operators.filter_op, against): 
    4801            return Grouping(self) 
    4802        else: 
    4803            return self 
    4804 
    4805    if not TYPE_CHECKING: 
    4806 
    4807        @util.memoized_property 
    4808        def type(self) -> TypeEngine[_T]:  # noqa: A001 
    4809            return self.func.type 
    4810 
    4811    @util.ro_non_memoized_property 
    4812    def _from_objects(self) -> List[FromClause]: 
    4813        return list( 
    4814            itertools.chain( 
    4815                *[ 
    4816                    c._from_objects 
    4817                    for c in (self.func, self.criterion) 
    4818                    if c is not None 
    4819                ] 
    4820            ) 
    4821        ) 
    4822 
    4823 
    4824class NamedColumn(KeyedColumnElement[_T]): 
    4825    is_literal = False 
    4826    table: Optional[FromClause] = None 
    4827    name: str 
    4828    key: str 
    4829 
    4830    def _compare_name_for_result(self, other): 
    4831        return (hasattr(other, "name") and self.name == other.name) or ( 
    4832            hasattr(other, "_label") and self._label == other._label 
    4833        ) 
    4834 
    4835    @util.ro_memoized_property 
    4836    def description(self) -> str: 
    4837        return self.name 
    4838 
    4839    @HasMemoized.memoized_attribute 
    4840    def _tq_key_label(self) -> Optional[str]: 
    4841        """table qualified label based on column key. 
    4842 
    4843        for table-bound columns this is <tablename>_<column key/proxy key>; 
    4844 
    4845        all other expressions it resolves to key/proxy key. 
    4846 
    4847        """ 
    4848        proxy_key = self._proxy_key 
    4849        if proxy_key and proxy_key != self.name: 
    4850            return self._gen_tq_label(proxy_key) 
    4851        else: 
    4852            return self._tq_label 
    4853 
    4854    @HasMemoized.memoized_attribute 
    4855    def _tq_label(self) -> Optional[str]: 
    4856        """table qualified label based on column name. 
    4857 
    4858        for table-bound columns this is <tablename>_<columnname>; all other 
    4859        expressions it resolves to .name. 
    4860 
    4861        """ 
    4862        return self._gen_tq_label(self.name) 
    4863 
    4864    @HasMemoized.memoized_attribute 
    4865    def _render_label_in_columns_clause(self): 
    4866        return True 
    4867 
    4868    @HasMemoized.memoized_attribute 
    4869    def _non_anon_label(self): 
    4870        return self.name 
    4871 
    4872    def _gen_tq_label( 
    4873        self, name: str, dedupe_on_key: bool = True 
    4874    ) -> Optional[str]: 
    4875        return name 
    4876 
    4877    def _bind_param( 
    4878        self, 
    4879        operator: OperatorType, 
    4880        obj: Any, 
    4881        type_: Optional[TypeEngine[_T]] = None, 
    4882        expanding: bool = False, 
    4883    ) -> BindParameter[_T]: 
    4884        return BindParameter( 
    4885            self.key, 
    4886            obj, 
    4887            _compared_to_operator=operator, 
    4888            _compared_to_type=self.type, 
    4889            type_=type_, 
    4890            unique=True, 
    4891            expanding=expanding, 
    4892        ) 
    4893 
    4894    def _make_proxy( 
    4895        self, 
    4896        selectable: FromClause, 
    4897        *, 
    4898        primary_key: ColumnSet, 
    4899        foreign_keys: Set[KeyedColumnElement[Any]], 
    4900        name: Optional[str] = None, 
    4901        key: Optional[str] = None, 
    4902        name_is_truncatable: bool = False, 
    4903        compound_select_cols: Optional[Sequence[ColumnElement[Any]]] = None, 
    4904        disallow_is_literal: bool = False, 
    4905        **kw: Any, 
    4906    ) -> typing_Tuple[str, ColumnClause[_T]]: 
    4907        c = ColumnClause( 
    4908            ( 
    4909                coercions.expect(roles.TruncatedLabelRole, name or self.name) 
    4910                if name_is_truncatable 
    4911                else (name or self.name) 
    4912            ), 
    4913            type_=self.type, 
    4914            _selectable=selectable, 
    4915            is_literal=False, 
    4916        ) 
    4917 
    4918        c._propagate_attrs = selectable._propagate_attrs 
    4919        if name is None: 
    4920            c.key = self.key 
    4921        if compound_select_cols: 
    4922            c._proxies = list(compound_select_cols) 
    4923        else: 
    4924            c._proxies = [self] 
    4925 
    4926        if selectable._is_clone_of is not None: 
    4927            c._is_clone_of = selectable._is_clone_of.columns.get(c.key) 
    4928        return c.key, c 
    4929 
    4930 
    4931_PS = ParamSpec("_PS") 
    4932 
    4933 
    4934class Label(roles.LabeledColumnExprRole[_T], NamedColumn[_T]): 
    4935    """Represents a column label (AS). 
    4936 
    4937    Represent a label, as typically applied to any column-level 
    4938    element using the ``AS`` sql keyword. 
    4939 
    4940    """ 
    4941 
    4942    __visit_name__ = "label" 
    4943 
    4944    _traverse_internals: _TraverseInternalsType = [ 
    4945        ("name", InternalTraversal.dp_anon_name), 
    4946        ("type", InternalTraversal.dp_type), 
    4947        ("_element", InternalTraversal.dp_clauseelement), 
    4948    ] 
    4949 
    4950    _cache_key_traversal = [ 
    4951        ("name", InternalTraversal.dp_anon_name), 
    4952        ("_element", InternalTraversal.dp_clauseelement), 
    4953    ] 
    4954 
    4955    _element: ColumnElement[_T] 
    4956    name: str 
    4957 
    4958    def __init__( 
    4959        self, 
    4960        name: Optional[str], 
    4961        element: _ColumnExpressionArgument[_T], 
    4962        type_: Optional[_TypeEngineArgument[_T]] = None, 
    4963    ): 
    4964        orig_element = element 
    4965        element = coercions.expect( 
    4966            roles.ExpressionElementRole, 
    4967            element, 
    4968            apply_propagate_attrs=self, 
    4969        ) 
    4970        while isinstance(element, Label): 
    4971            # TODO: this is only covered in test_text.py, but nothing 
    4972            # fails if it's removed.  determine rationale 
    4973            element = element.element 
    4974 
    4975        if name: 
    4976            self.name = name 
    4977        else: 
    4978            self.name = _anonymous_label.safe_construct( 
    4979                id(self), getattr(element, "name", "anon") 
    4980            ) 
    4981            if isinstance(orig_element, Label): 
    4982                # TODO: no coverage for this block, again would be in 
    4983                # test_text.py where the resolve_label concept is important 
    4984                self._resolve_label = orig_element._label 
    4985 
    4986        self.key = self._tq_label = self._tq_key_label = self.name 
    4987        self._element = element 
    4988 
    4989        self.type = ( 
    4990            type_api.to_instance(type_) 
    4991            if type_ is not None 
    4992            else self._element.type 
    4993        ) 
    4994 
    4995        self._proxies = [element] 
    4996 
    4997    def __reduce__(self): 
    4998        return self.__class__, (self.name, self._element, self.type) 
    4999 
    5000    @HasMemoized.memoized_attribute 
    5001    def _render_label_in_columns_clause(self): 
    5002        return True 
    5003 
    5004    def _bind_param(self, operator, obj, type_=None, expanding=False): 
    5005        return BindParameter( 
    5006            None, 
    5007            obj, 
    5008            _compared_to_operator=operator, 
    5009            type_=type_, 
    5010            _compared_to_type=self.type, 
    5011            unique=True, 
    5012            expanding=expanding, 
    5013        ) 
    5014 
    5015    @util.memoized_property 
    5016    def _is_implicitly_boolean(self): 
    5017        return self.element._is_implicitly_boolean 
    5018 
    5019    @HasMemoized.memoized_attribute 
    5020    def _allow_label_resolve(self): 
    5021        return self.element._allow_label_resolve 
    5022 
    5023    @property 
    5024    def _order_by_label_element(self): 
    5025        return self 
    5026 
    5027    def as_reference(self) -> _label_reference[_T]: 
    5028        """refer to this labeled expression in a clause such as GROUP BY, 
    5029        ORDER BY etc. as the label name itself, without expanding 
    5030        into the full expression. 
    5031 
    5032        .. versionadded:: 2.1 
    5033 
    5034        """ 
    5035        return _label_reference(self) 
    5036 
    5037    @HasMemoized.memoized_attribute 
    5038    def element(self) -> ColumnElement[_T]: 
    5039        return self._element.self_group(against=operators.as_) 
    5040 
    5041    def self_group(self, against: Optional[OperatorType] = None) -> Label[_T]: 
    5042        return self._apply_to_inner(self._element.self_group, against=against) 
    5043 
    5044    def _negate(self): 
    5045        return self._apply_to_inner(self._element._negate) 
    5046 
    5047    def _apply_to_inner( 
    5048        self, 
    5049        fn: Callable[_PS, ColumnElement[_T]], 
    5050        *arg: _PS.args, 
    5051        **kw: _PS.kwargs, 
    5052    ) -> Label[_T]: 
    5053        sub_element = fn(*arg, **kw) 
    5054        if sub_element is not self._element: 
    5055            return Label(self.name, sub_element, type_=self.type) 
    5056        else: 
    5057            return self 
    5058 
    5059    @property 
    5060    def primary_key(self):  # type: ignore[override] 
    5061        return self.element.primary_key 
    5062 
    5063    @property 
    5064    def foreign_keys(self):  # type: ignore[override] 
    5065        return self.element.foreign_keys 
    5066 
    5067    def _copy_internals( 
    5068        self, 
    5069        *, 
    5070        clone: _CloneCallableType = _clone, 
    5071        anonymize_labels: bool = False, 
    5072        **kw: Any, 
    5073    ) -> None: 
    5074        self._reset_memoizations() 
    5075        self._element = clone(self._element, **kw) 
    5076        if anonymize_labels: 
    5077            self.name = _anonymous_label.safe_construct( 
    5078                id(self), getattr(self.element, "name", "anon") 
    5079            ) 
    5080            self.key = self._tq_label = self._tq_key_label = self.name 
    5081 
    5082    @util.ro_non_memoized_property 
    5083    def _from_objects(self) -> List[FromClause]: 
    5084        return self.element._from_objects 
    5085 
    5086    def _make_proxy( 
    5087        self, 
    5088        selectable: FromClause, 
    5089        *, 
    5090        primary_key: ColumnSet, 
    5091        foreign_keys: Set[KeyedColumnElement[Any]], 
    5092        name: Optional[str] = None, 
    5093        compound_select_cols: Optional[Sequence[ColumnElement[Any]]] = None, 
    5094        **kw: Any, 
    5095    ) -> typing_Tuple[str, ColumnClause[_T]]: 
    5096        name = self.name if not name else name 
    5097 
    5098        key, e = self.element._make_proxy( 
    5099            selectable, 
    5100            name=name, 
    5101            disallow_is_literal=True, 
    5102            name_is_truncatable=isinstance(name, _truncated_label), 
    5103            compound_select_cols=compound_select_cols, 
    5104            primary_key=primary_key, 
    5105            foreign_keys=foreign_keys, 
    5106        ) 
    5107 
    5108        # there was a note here to remove this assertion, which was here 
    5109        # to determine if we later could support a use case where 
    5110        # the key and name of a label are separate.  But I don't know what 
    5111        # that case was.  For now, this is an unexpected case that occurs 
    5112        # when a label name conflicts with other columns and select() 
    5113        # is attempting to disambiguate an explicit label, which is not what 
    5114        # the user would want.   See issue #6090. 
    5115        if key != self.name and not isinstance(self.name, _anonymous_label): 
    5116            raise exc.InvalidRequestError( 
    5117                "Label name %s is being renamed to an anonymous label due " 
    5118                "to disambiguation " 
    5119                "which is not supported right now.  Please use unique names " 
    5120                "for explicit labels." % (self.name) 
    5121            ) 
    5122 
    5123        e._propagate_attrs = selectable._propagate_attrs 
    5124        e._proxies.append(self) 
    5125        if self.type is not None: 
    5126            e.type = self.type 
    5127 
    5128        return self.key, e 
    5129 
    5130 
    5131class ColumnClause( 
    5132    roles.DDLReferredColumnRole, 
    5133    roles.LabeledColumnExprRole[_T], 
    5134    roles.StrAsPlainColumnRole, 
    5135    Immutable, 
    5136    NamedColumn[_T], 
    5137): 
    5138    """Represents a column expression from any textual string. 
    5139 
    5140    The :class:`.ColumnClause`, a lightweight analogue to the 
    5141    :class:`_schema.Column` class, is typically invoked using the 
    5142    :func:`_expression.column` function, as in:: 
    5143 
    5144        from sqlalchemy import column 
    5145 
    5146        id, name = column("id"), column("name") 
    5147        stmt = select(id, name).select_from("user") 
    5148 
    5149    The above statement would produce SQL like: 
    5150 
    5151    .. sourcecode:: sql 
    5152 
    5153        SELECT id, name FROM user 
    5154 
    5155    :class:`.ColumnClause` is the immediate superclass of the schema-specific 
    5156    :class:`_schema.Column` object.  While the :class:`_schema.Column` 
    5157    class has all the 
    5158    same capabilities as :class:`.ColumnClause`, the :class:`.ColumnClause` 
    5159    class is usable by itself in those cases where behavioral requirements 
    5160    are limited to simple SQL expression generation.  The object has none of 
    5161    the associations with schema-level metadata or with execution-time 
    5162    behavior that :class:`_schema.Column` does, 
    5163    so in that sense is a "lightweight" 
    5164    version of :class:`_schema.Column`. 
    5165 
    5166    Full details on :class:`.ColumnClause` usage is at 
    5167    :func:`_expression.column`. 
    5168 
    5169    .. seealso:: 
    5170 
    5171        :func:`_expression.column` 
    5172 
    5173        :class:`_schema.Column` 
    5174 
    5175    """ 
    5176 
    5177    table: Optional[FromClause] 
    5178    is_literal: bool 
    5179 
    5180    __visit_name__ = "column" 
    5181 
    5182    _traverse_internals: _TraverseInternalsType = [ 
    5183        ("name", InternalTraversal.dp_anon_name), 
    5184        ("type", InternalTraversal.dp_type), 
    5185        ("table", InternalTraversal.dp_clauseelement), 
    5186        ("is_literal", InternalTraversal.dp_boolean), 
    5187    ] 
    5188 
    5189    onupdate: Optional[DefaultGenerator] = None 
    5190    default: Optional[DefaultGenerator] = None 
    5191    server_default: Optional[FetchedValue] = None 
    5192    server_onupdate: Optional[FetchedValue] = None 
    5193 
    5194    _is_multiparam_column = False 
    5195 
    5196    @property 
    5197    def _is_star(self):  # type: ignore[override] 
    5198        return self.is_literal and self.name == "*" 
    5199 
    5200    def __init__( 
    5201        self, 
    5202        text: str, 
    5203        type_: Optional[_TypeEngineArgument[_T]] = None, 
    5204        is_literal: bool = False, 
    5205        _selectable: Optional[FromClause] = None, 
    5206    ): 
    5207        self.key = self.name = text 
    5208        self.table = _selectable 
    5209 
    5210        # if type is None, we get NULLTYPE, which is our _T.  But I don't 
    5211        # know how to get the overloads to express that correctly 
    5212        self.type = type_api.to_instance(type_)  # type: ignore 
    5213 
    5214        self.is_literal = is_literal 
    5215 
    5216    def get_children(self, *, column_tables=False, **kw): 
    5217        # override base get_children() to not return the Table 
    5218        # or selectable that is parent to this column.  Traversals 
    5219        # expect the columns of tables and subqueries to be leaf nodes. 
    5220        return [] 
    5221 
    5222    @property 
    5223    def entity_namespace(self): 
    5224        if self.table is not None: 
    5225            return self.table.entity_namespace 
    5226        else: 
    5227            return super().entity_namespace 
    5228 
    5229    def _clone(self, detect_subquery_cols=False, **kw): 
    5230        if ( 
    5231            detect_subquery_cols 
    5232            and self.table is not None 
    5233            and self.table._is_subquery 
    5234        ): 
    5235            clone = kw.pop("clone") 
    5236            table = clone(self.table, **kw) 
    5237            new = table.c.corresponding_column(self) 
    5238            return new 
    5239 
    5240        return super()._clone(**kw) 
    5241 
    5242    @HasMemoized_ro_memoized_attribute 
    5243    def _from_objects(self) -> List[FromClause]: 
    5244        t = self.table 
    5245        if t is not None: 
    5246            return [t] 
    5247        else: 
    5248            return [] 
    5249 
    5250    @HasMemoized.memoized_attribute 
    5251    def _render_label_in_columns_clause(self): 
    5252        return self.table is not None 
    5253 
    5254    @property 
    5255    def _ddl_label(self): 
    5256        return self._gen_tq_label(self.name, dedupe_on_key=False) 
    5257 
    5258    def _compare_name_for_result(self, other): 
    5259        if ( 
    5260            self.is_literal 
    5261            or self.table is None 
    5262            or self.table._is_textual 
    5263            or not hasattr(other, "proxy_set") 
    5264            or ( 
    5265                isinstance(other, ColumnClause) 
    5266                and ( 
    5267                    other.is_literal 
    5268                    or other.table is None 
    5269                    or other.table._is_textual 
    5270                ) 
    5271            ) 
    5272        ): 
    5273            return (hasattr(other, "name") and self.name == other.name) or ( 
    5274                hasattr(other, "_tq_label") 
    5275                and self._tq_label == other._tq_label 
    5276            ) 
    5277        else: 
    5278            return other.proxy_set.intersection(self.proxy_set) 
    5279 
    5280    def _gen_tq_label( 
    5281        self, name: str, dedupe_on_key: bool = True 
    5282    ) -> Optional[str]: 
    5283        """generate table-qualified label 
    5284 
    5285        for a table-bound column this is <tablename>_<columnname>. 
    5286 
    5287        used primarily for LABEL_STYLE_TABLENAME_PLUS_COL 
    5288        as well as the .columns collection on a Join object. 
    5289 
    5290        """ 
    5291        label: str 
    5292        t = self.table 
    5293        if self.is_literal: 
    5294            return None 
    5295        elif t is not None and is_named_from_clause(t): 
    5296            if has_schema_attr(t) and t.schema: 
    5297                label = ( 
    5298                    t.schema.replace(".", "_") + "_" + t.name + ("_" + name) 
    5299                ) 
    5300            else: 
    5301                assert not TYPE_CHECKING or isinstance(t, NamedFromClause) 
    5302                label = t.name + ("_" + name) 
    5303 
    5304            # propagate name quoting rules for labels. 
    5305            if is_quoted_name(name) and name.quote is not None: 
    5306                if is_quoted_name(label): 
    5307                    label.quote = name.quote 
    5308                else: 
    5309                    label = quoted_name(label, name.quote) 
    5310            elif is_quoted_name(t.name) and t.name.quote is not None: 
    5311                # can't get this situation to occur, so let's 
    5312                # assert false on it for now 
    5313                assert not isinstance(label, quoted_name) 
    5314                label = quoted_name(label, t.name.quote) 
    5315 
    5316            if dedupe_on_key: 
    5317                # ensure the label name doesn't conflict with that of an 
    5318                # existing column.   note that this implies that any Column 
    5319                # must **not** set up its _label before its parent table has 
    5320                # all of its other Column objects set up.  There are several 
    5321                # tables in the test suite which will fail otherwise; example: 
    5322                # table "owner" has columns "name" and "owner_name".  Therefore 
    5323                # column owner.name cannot use the label "owner_name", it has 
    5324                # to be "owner_name_1". 
    5325                if label in t.c: 
    5326                    _label = label 
    5327                    counter = 1 
    5328                    while _label in t.c: 
    5329                        _label = label + f"_{counter}" 
    5330                        counter += 1 
    5331                    label = _label 
    5332 
    5333            return coercions.expect(roles.TruncatedLabelRole, label) 
    5334 
    5335        else: 
    5336            return name 
    5337 
    5338    def _make_proxy( 
    5339        self, 
    5340        selectable: FromClause, 
    5341        *, 
    5342        primary_key: ColumnSet, 
    5343        foreign_keys: Set[KeyedColumnElement[Any]], 
    5344        name: Optional[str] = None, 
    5345        key: Optional[str] = None, 
    5346        name_is_truncatable: bool = False, 
    5347        compound_select_cols: Optional[Sequence[ColumnElement[Any]]] = None, 
    5348        disallow_is_literal: bool = False, 
    5349        **kw: Any, 
    5350    ) -> typing_Tuple[str, ColumnClause[_T]]: 
    5351        # the "is_literal" flag normally should never be propagated; a proxied 
    5352        # column is always a SQL identifier and never the actual expression 
    5353        # being evaluated. however, there is a case where the "is_literal" flag 
    5354        # might be used to allow the given identifier to have a fixed quoting 
    5355        # pattern already, so maintain the flag for the proxy unless a 
    5356        # :class:`.Label` object is creating the proxy.  See [ticket:4730]. 
    5357        is_literal = ( 
    5358            not disallow_is_literal 
    5359            and self.is_literal 
    5360            and ( 
    5361                # note this does not accommodate for quoted_name differences 
    5362                # right now 
    5363                name is None 
    5364                or name == self.name 
    5365            ) 
    5366        ) 
    5367        c = self._constructor( 
    5368            ( 
    5369                coercions.expect(roles.TruncatedLabelRole, name or self.name) 
    5370                if name_is_truncatable 
    5371                else (name or self.name) 
    5372            ), 
    5373            type_=self.type, 
    5374            _selectable=selectable, 
    5375            is_literal=is_literal, 
    5376        ) 
    5377        c._propagate_attrs = selectable._propagate_attrs 
    5378        if name is None: 
    5379            c.key = self.key 
    5380        if compound_select_cols: 
    5381            c._proxies = list(compound_select_cols) 
    5382        else: 
    5383            c._proxies = [self] 
    5384 
    5385        if selectable._is_clone_of is not None: 
    5386            c._is_clone_of = selectable._is_clone_of.columns.get(c.key) 
    5387        return c.key, c 
    5388 
    5389 
    5390class TableValuedColumn(NamedColumn[_T]): 
    5391    __visit_name__ = "table_valued_column" 
    5392 
    5393    _traverse_internals: _TraverseInternalsType = [ 
    5394        ("name", InternalTraversal.dp_anon_name), 
    5395        ("type", InternalTraversal.dp_type), 
    5396        ("scalar_alias", InternalTraversal.dp_clauseelement), 
    5397    ] 
    5398 
    5399    def __init__(self, scalar_alias: NamedFromClause, type_: TypeEngine[_T]): 
    5400        self.scalar_alias = scalar_alias 
    5401        self.key = self.name = scalar_alias.name 
    5402        self.type = type_ 
    5403 
    5404    def _copy_internals( 
    5405        self, clone: _CloneCallableType = _clone, **kw: Any 
    5406    ) -> None: 
    5407        self.scalar_alias = clone(self.scalar_alias, **kw) 
    5408        self.key = self.name = self.scalar_alias.name 
    5409 
    5410    @util.ro_non_memoized_property 
    5411    def _from_objects(self) -> List[FromClause]: 
    5412        return [self.scalar_alias] 
    5413 
    5414 
    5415class CollationClause(ColumnElement[str]): 
    5416    __visit_name__ = "collation" 
    5417 
    5418    _traverse_internals: _TraverseInternalsType = [ 
    5419        ("collation", InternalTraversal.dp_string) 
    5420    ] 
    5421 
    5422    @classmethod 
    5423    @util.preload_module("sqlalchemy.sql.sqltypes") 
    5424    def _create_collation_expression( 
    5425        cls, expression: _ColumnExpressionArgument[str], collation: str 
    5426    ) -> BinaryExpression[str]: 
    5427 
    5428        sqltypes = util.preloaded.sql_sqltypes 
    5429 
    5430        expr = coercions.expect(roles.ExpressionElementRole[str], expression) 
    5431 
    5432        if expr.type._type_affinity is sqltypes.String: 
    5433            collate_type = expr.type._with_collation(collation) 
    5434        else: 
    5435            collate_type = expr.type 
    5436 
    5437        return BinaryExpression( 
    5438            expr, 
    5439            CollationClause(collation), 
    5440            operators.collate, 
    5441            type_=collate_type, 
    5442        ) 
    5443 
    5444    def __init__(self, collation): 
    5445        self.collation = collation 
    5446 
    5447 
    5448class _IdentifiedClause(Executable, ClauseElement): 
    5449    __visit_name__ = "identified" 
    5450 
    5451    def __init__(self, ident): 
    5452        self.ident = ident 
    5453 
    5454 
    5455class SavepointClause(_IdentifiedClause): 
    5456    __visit_name__ = "savepoint" 
    5457    inherit_cache = False 
    5458 
    5459 
    5460class RollbackToSavepointClause(_IdentifiedClause): 
    5461    __visit_name__ = "rollback_to_savepoint" 
    5462    inherit_cache = False 
    5463 
    5464 
    5465class ReleaseSavepointClause(_IdentifiedClause): 
    5466    __visit_name__ = "release_savepoint" 
    5467    inherit_cache = False 
    5468 
    5469 
    5470class quoted_name(util.MemoizedSlots, str): 
    5471    """Represent a SQL identifier combined with quoting preferences. 
    5472 
    5473    :class:`.quoted_name` is a Python unicode/str subclass which 
    5474    represents a particular identifier name along with a 
    5475    ``quote`` flag.  This ``quote`` flag, when set to 
    5476    ``True`` or ``False``, overrides automatic quoting behavior 
    5477    for this identifier in order to either unconditionally quote 
    5478    or to not quote the name.  If left at its default of ``None``, 
    5479    quoting behavior is applied to the identifier on a per-backend basis 
    5480    based on an examination of the token itself. 
    5481 
    5482    A :class:`.quoted_name` object with ``quote=True`` is also 
    5483    prevented from being modified in the case of a so-called 
    5484    "name normalize" option.  Certain database backends, such as 
    5485    Oracle Database, Firebird, and DB2 "normalize" case-insensitive names 
    5486    as uppercase.  The SQLAlchemy dialects for these backends 
    5487    convert from SQLAlchemy's lower-case-means-insensitive convention 
    5488    to the upper-case-means-insensitive conventions of those backends. 
    5489    The ``quote=True`` flag here will prevent this conversion from occurring 
    5490    to support an identifier that's quoted as all lower case against 
    5491    such a backend. 
    5492 
    5493    The :class:`.quoted_name` object is normally created automatically 
    5494    when specifying the name for key schema constructs such as 
    5495    :class:`_schema.Table`, :class:`_schema.Column`, and others. 
    5496    The class can also be 
    5497    passed explicitly as the name to any function that receives a name which 
    5498    can be quoted.  Such as to use the :meth:`_engine.Engine.has_table` 
    5499    method with 
    5500    an unconditionally quoted name:: 
    5501 
    5502        from sqlalchemy import create_engine 
    5503        from sqlalchemy import inspect 
    5504        from sqlalchemy.sql import quoted_name 
    5505 
    5506        engine = create_engine("oracle+oracledb://some_dsn") 
    5507        print(inspect(engine).has_table(quoted_name("some_table", True))) 
    5508 
    5509    The above logic will run the "has table" logic against the Oracle Database 
    5510    backend, passing the name exactly as ``"some_table"`` without converting to 
    5511    upper case. 
    5512 
    5513    """ 
    5514 
    5515    __slots__ = "quote", "lower", "upper" 
    5516 
    5517    quote: Optional[bool] 
    5518 
    5519    @overload 
    5520    @classmethod 
    5521    def construct(cls, value: str, quote: Optional[bool]) -> quoted_name: ... 
    5522 
    5523    @overload 
    5524    @classmethod 
    5525    def construct(cls, value: None, quote: Optional[bool]) -> None: ... 
    5526 
    5527    @classmethod 
    5528    def construct( 
    5529        cls, value: Optional[str], quote: Optional[bool] 
    5530    ) -> Optional[quoted_name]: 
    5531        if value is None: 
    5532            return None 
    5533        else: 
    5534            return quoted_name(value, quote) 
    5535 
    5536    def __new__(cls, value: str, quote: Optional[bool]) -> quoted_name: 
    5537        assert ( 
    5538            value is not None 
    5539        ), "use quoted_name.construct() for None passthrough" 
    5540        if isinstance(value, cls) and (quote is None or value.quote == quote): 
    5541            return value 
    5542        self = super().__new__(cls, value) 
    5543 
    5544        self.quote = quote 
    5545        return self 
    5546 
    5547    def __reduce__(self): 
    5548        return quoted_name, (str(self), self.quote) 
    5549 
    5550    def _memoized_method_lower(self): 
    5551        if self.quote: 
    5552            return self 
    5553        else: 
    5554            return str(self).lower() 
    5555 
    5556    def _memoized_method_upper(self): 
    5557        if self.quote: 
    5558            return self 
    5559        else: 
    5560            return str(self).upper() 
    5561 
    5562 
    5563def _find_columns(clause: ClauseElement) -> Set[ColumnClause[Any]]: 
    5564    """locate Column objects within the given expression.""" 
    5565 
    5566    cols: Set[ColumnClause[Any]] = set() 
    5567    traverse(clause, {}, {"column": cols.add}) 
    5568    return cols 
    5569 
    5570 
    5571def _type_from_args(args: Sequence[ColumnElement[_T]]) -> TypeEngine[_T]: 
    5572    for a in args: 
    5573        if not a.type._isnull: 
    5574            return a.type 
    5575    else: 
    5576        return type_api.NULLTYPE  # type: ignore 
    5577 
    5578 
    5579def _corresponding_column_or_error(fromclause, column, require_embedded=False): 
    5580    c = fromclause.corresponding_column( 
    5581        column, require_embedded=require_embedded 
    5582    ) 
    5583    if c is None: 
    5584        raise exc.InvalidRequestError( 
    5585            "Given column '%s', attached to table '%s', " 
    5586            "failed to locate a corresponding column from table '%s'" 
    5587            % (column, getattr(column, "table", None), fromclause.description) 
    5588        ) 
    5589    return c 
    5590 
    5591 
    5592class _memoized_property_but_not_nulltype( 
    5593    util.memoized_property["TypeEngine[_T]"] 
    5594): 
    5595    """memoized property, but dont memoize NullType""" 
    5596 
    5597    def __get__(self, obj, cls): 
    5598        if obj is None: 
    5599            return self 
    5600        result = self.fget(obj) 
    5601        if not result._isnull: 
    5602            obj.__dict__[self.__name__] = result 
    5603        return result 
    5604 
    5605 
    5606class AnnotatedColumnElement(Annotated): 
    5607    _Annotated__element: ColumnElement[Any] 
    5608 
    5609    def __init__(self, element, values): 
    5610        Annotated.__init__(self, element, values) 
    5611        for attr in ( 
    5612            "comparator", 
    5613            "_proxy_key", 
    5614            "_tq_key_label", 
    5615            "_tq_label", 
    5616            "_non_anon_label", 
    5617            "type", 
    5618        ): 
    5619            self.__dict__.pop(attr, None) 
    5620        for attr in ("name", "key", "table"): 
    5621            if self.__dict__.get(attr, False) is None: 
    5622                self.__dict__.pop(attr) 
    5623 
    5624    def _with_annotations(self, values): 
    5625        clone = super()._with_annotations(values) 
    5626        for attr in ( 
    5627            "comparator", 
    5628            "_proxy_key", 
    5629            "_tq_key_label", 
    5630            "_tq_label", 
    5631            "_non_anon_label", 
    5632        ): 
    5633            clone.__dict__.pop(attr, None) 
    5634        return clone 
    5635 
    5636    @util.memoized_property 
    5637    def name(self): 
    5638        """pull 'name' from parent, if not present""" 
    5639        return self._Annotated__element.name 
    5640 
    5641    @_memoized_property_but_not_nulltype 
    5642    def type(self): 
    5643        """pull 'type' from parent and don't cache if null. 
    5644 
    5645        type is routinely changed on existing columns within the 
    5646        mapped_column() initialization process, and "type" is also consulted 
    5647        during the creation of SQL expressions.  Therefore it can change after 
    5648        it was already retrieved.  At the same time we don't want annotated 
    5649        objects having overhead when expressions are produced, so continue 
    5650        to memoize, but only when we have a non-null type. 
    5651 
    5652        """ 
    5653        return self._Annotated__element.type 
    5654 
    5655    @util.memoized_property 
    5656    def table(self): 
    5657        """pull 'table' from parent, if not present""" 
    5658        return self._Annotated__element.table 
    5659 
    5660    @util.memoized_property 
    5661    def key(self): 
    5662        """pull 'key' from parent, if not present""" 
    5663        return self._Annotated__element.key 
    5664 
    5665    @util.memoized_property 
    5666    def info(self) -> _InfoType: 
    5667        if TYPE_CHECKING: 
    5668            assert isinstance(self._Annotated__element, Column) 
    5669        return self._Annotated__element.info 
    5670 
    5671    @util.memoized_property 
    5672    def _anon_name_label(self) -> str: 
    5673        return self._Annotated__element._anon_name_label 
    5674 
    5675 
    5676class _truncated_label(quoted_name): 
    5677    """A unicode subclass used to identify symbolic " 
    5678    "names that may require truncation.""" 
    5679 
    5680    __slots__ = () 
    5681 
    5682    def __new__(cls, value: str, quote: Optional[bool] = None) -> Any: 
    5683        quote = getattr(value, "quote", quote) 
    5684        # return super(_truncated_label, cls).__new__(cls, value, quote, True) 
    5685        return super().__new__(cls, value, quote) 
    5686 
    5687    def __reduce__(self) -> Any: 
    5688        return self.__class__, (str(self), self.quote) 
    5689 
    5690    def apply_map(self, map_: Mapping[str, Any]) -> str: 
    5691        return self 
    5692 
    5693 
    5694class conv(_truncated_label): 
    5695    """Mark a string indicating that a name has already been converted 
    5696    by a naming convention. 
    5697 
    5698    This is a string subclass that indicates a name that should not be 
    5699    subject to any further naming conventions. 
    5700 
    5701    E.g. when we create a :class:`.Constraint` using a naming convention 
    5702    as follows:: 
    5703 
    5704        m = MetaData( 
    5705            naming_convention={"ck": "ck_%(table_name)s_%(constraint_name)s"} 
    5706        ) 
    5707        t = Table( 
    5708            "t", m, Column("x", Integer), CheckConstraint("x > 5", name="x5") 
    5709        ) 
    5710 
    5711    The name of the above constraint will be rendered as ``"ck_t_x5"``. 
    5712    That is, the existing name ``x5`` is used in the naming convention as the 
    5713    ``constraint_name`` token. 
    5714 
    5715    In some situations, such as in migration scripts, we may be rendering 
    5716    the above :class:`.CheckConstraint` with a name that's already been 
    5717    converted.  In order to make sure the name isn't double-modified, the 
    5718    new name is applied using the :func:`_schema.conv` marker.  We can 
    5719    use this explicitly as follows:: 
    5720 
    5721 
    5722        m = MetaData( 
    5723            naming_convention={"ck": "ck_%(table_name)s_%(constraint_name)s"} 
    5724        ) 
    5725        t = Table( 
    5726            "t", 
    5727            m, 
    5728            Column("x", Integer), 
    5729            CheckConstraint("x > 5", name=conv("ck_t_x5")), 
    5730        ) 
    5731 
    5732    Where above, the :func:`_schema.conv` marker indicates that the constraint 
    5733    name here is final, and the name will render as ``"ck_t_x5"`` and not 
    5734    ``"ck_t_ck_t_x5"`` 
    5735 
    5736    .. seealso:: 
    5737 
    5738        :ref:`constraint_naming_conventions` 
    5739 
    5740    """ 
    5741 
    5742    __slots__ = () 
    5743 
    5744 
    5745# for backwards compatibility in case 
    5746# someone is re-implementing the 
    5747# _truncated_identifier() sequence in a custom 
    5748# compiler 
    5749_generated_label = _truncated_label 
    5750_anonymous_label_escape = re.compile(r"[%\(\) \$]+") 
    5751 
    5752 
    5753class _anonymous_label(_truncated_label): 
    5754    """A unicode subclass used to identify anonymously 
    5755    generated names.""" 
    5756 
    5757    __slots__ = () 
    5758 
    5759    @classmethod 
    5760    def safe_construct_with_key( 
    5761        cls, seed: int, body: str, sanitize_key: bool = False 
    5762    ) -> typing_Tuple[_anonymous_label, str]: 
    5763        # need to escape chars that interfere with format 
    5764        # strings in any case, issue #8724 
    5765        body = _anonymous_label_escape.sub("_", body) 
    5766 
    5767        if sanitize_key: 
    5768            # sanitize_key is then an extra step used by BindParameter 
    5769            body = body.strip("_") 
    5770 
    5771        key = f"{seed} {body.replace('%', '%%')}" 
    5772        label = _anonymous_label(f"%({key})s") 
    5773        return label, key 
    5774 
    5775    @classmethod 
    5776    def safe_construct( 
    5777        cls, seed: int, body: str, sanitize_key: bool = False 
    5778    ) -> _anonymous_label: 
    5779        # need to escape chars that interfere with format 
    5780        # strings in any case, issue #8724 
    5781        body = _anonymous_label_escape.sub("_", body) 
    5782 
    5783        if sanitize_key: 
    5784            # sanitize_key is then an extra step used by BindParameter 
    5785            body = body.strip("_") 
    5786 
    5787        return _anonymous_label(f"%({seed} {body.replace('%', '%%')})s") 
    5788 
    5789    def __add__(self, other: str) -> _anonymous_label: 
    5790        if "%" in other and not isinstance(other, _anonymous_label): 
    5791            other = str(other).replace("%", "%%") 
    5792        else: 
    5793            other = str(other) 
    5794 
    5795        return _anonymous_label( 
    5796            quoted_name( 
    5797                str.__add__(self, other), 
    5798                self.quote, 
    5799            ) 
    5800        ) 
    5801 
    5802    def __radd__(self, other: str) -> _anonymous_label: 
    5803        if "%" in other and not isinstance(other, _anonymous_label): 
    5804            other = str(other).replace("%", "%%") 
    5805        else: 
    5806            other = str(other) 
    5807 
    5808        return _anonymous_label( 
    5809            quoted_name( 
    5810                str.__add__(other, self), 
    5811                self.quote, 
    5812            ) 
    5813        ) 
    5814 
    5815    def apply_map(self, map_: Mapping[str, Any]) -> str: 
    5816        if self.quote is not None: 
    5817            # preserve quoting only if necessary 
    5818            return quoted_name(self % map_, self.quote) 
    5819        else: 
    5820            # else skip the constructor call 
    5821            return self % map_