Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes15kdownloads
selectable.py6933 linesDownload Raw Back to sql
1# sql/selectable.py
2# Copyright (C) 2005-2024 the SQLAlchemy authors and contributors
3# <see AUTHORS file>
4#
5# This module is part of SQLAlchemy and is released under
6# the MIT License: https://www.opensource.org/licenses/mit-license.php
7
8"""The :class:`_expression.FromClause` class of SQL expression elements,
9representing
10SQL tables and derived rowsets.
11
12"""
13
14from __future__ import annotations
15
16import collections
17from enum import Enum
18import itertools
19from typing import AbstractSet
20from typing import Any as TODO_Any
21from typing import Any
22from typing import Callable
23from typing import cast
24from typing import Dict
25from typing import Generic
26from typing import Iterable
27from typing import Iterator
28from typing import List
29from typing import NamedTuple
30from typing import NoReturn
31from typing import Optional
32from typing import overload
33from typing import Sequence
34from typing import Set
35from typing import Tuple
36from typing import Type
37from typing import TYPE_CHECKING
38from typing import TypeVar
39from typing import Union
40
41from . import cache_key
42from . import coercions
43from . import operators
44from . import roles
45from . import traversals
46from . import type_api
47from . import visitors
48from ._typing import _ColumnsClauseArgument
49from ._typing import _no_kw
50from ._typing import _TP
51from ._typing import is_column_element
52from ._typing import is_select_statement
53from ._typing import is_subquery
54from ._typing import is_table
55from ._typing import is_text_clause
56from .annotation import Annotated
57from .annotation import SupportsCloneAnnotations
58from .base import _clone
59from .base import _cloned_difference
60from .base import _cloned_intersection
61from .base import _entity_namespace_key
62from .base import _EntityNamespace
63from .base import _expand_cloned
64from .base import _from_objects
65from .base import _generative
66from .base import _never_select_column
67from .base import _NoArg
68from .base import _select_iterables
69from .base import CacheableOptions
70from .base import ColumnCollection
71from .base import ColumnSet
72from .base import CompileState
73from .base import DedupeColumnCollection
74from .base import Executable
75from .base import Generative
76from .base import HasCompileState
77from .base import HasMemoized
78from .base import Immutable
79from .coercions import _document_text_coercion
80from .elements import _anonymous_label
81from .elements import BindParameter
82from .elements import BooleanClauseList
83from .elements import ClauseElement
84from .elements import ClauseList
85from .elements import ColumnClause
86from .elements import ColumnElement
87from .elements import DQLDMLClauseElement
88from .elements import GroupedElement
89from .elements import literal_column
90from .elements import TableValuedColumn
91from .elements import UnaryExpression
92from .operators import OperatorType
93from .sqltypes import NULLTYPE
94from .visitors import _TraverseInternalsType
95from .visitors import InternalTraversal
96from .visitors import prefix_anon_map
97from .. import exc
98from .. import util
99from ..util import HasMemoized_ro_memoized_attribute
100from ..util.typing import Literal
101from ..util.typing import Protocol
102from ..util.typing import Self
103
104and_ = BooleanClauseList.and_
105
106_T = TypeVar("_T", bound=Any)
107
108if TYPE_CHECKING:
109    from ._typing import _ColumnExpressionArgument
110    from ._typing import _ColumnExpressionOrStrLabelArgument
111    from ._typing import _FromClauseArgument
112    from ._typing import _JoinTargetArgument
113    from ._typing import _LimitOffsetType
114    from ._typing import _MAYBE_ENTITY
115    from ._typing import _NOT_ENTITY
116    from ._typing import _OnClauseArgument
117    from ._typing import _SelectStatementForCompoundArgument
118    from ._typing import _T0
119    from ._typing import _T1
120    from ._typing import _T2
121    from ._typing import _T3
122    from ._typing import _T4
123    from ._typing import _T5
124    from ._typing import _T6
125    from ._typing import _T7
126    from ._typing import _TextCoercedExpressionArgument
127    from ._typing import _TypedColumnClauseArgument as _TCCA
128    from ._typing import _TypeEngineArgument
129    from .base import _AmbiguousTableNameMap
130    from .base import ExecutableOption
131    from .base import ReadOnlyColumnCollection
132    from .cache_key import _CacheKeyTraversalType
133    from .compiler import SQLCompiler
134    from .dml import Delete
135    from .dml import Update
136    from .elements import BinaryExpression
137    from .elements import KeyedColumnElement
138    from .elements import Label
139    from .elements import NamedColumn
140    from .elements import TextClause
141    from .functions import Function
142    from .schema import ForeignKey
143    from .schema import ForeignKeyConstraint
144    from .sqltypes import TableValueType
145    from .type_api import TypeEngine
146    from .visitors import _CloneCallableType
147
148
149_ColumnsClauseElement = Union["FromClause", ColumnElement[Any], "TextClause"]
150_LabelConventionCallable = Callable[
151    [Union["ColumnElement[Any]", "TextClause"]], Optional[str]
152]
153
154
155class _JoinTargetProtocol(Protocol):
156    @util.ro_non_memoized_property
157    def _from_objects(self) -> List[FromClause]: ...
158
159    @util.ro_non_memoized_property
160    def entity_namespace(self) -> _EntityNamespace: ...
161
162
163_JoinTargetElement = Union["FromClause", _JoinTargetProtocol]
164_OnClauseElement = Union["ColumnElement[bool]", _JoinTargetProtocol]
165
166_ForUpdateOfArgument = Union[
167    # single column, Table, ORM Entity
168    Union[
169        "_ColumnExpressionArgument[Any]",
170        "_FromClauseArgument",
171    ],
172    # or sequence of single column elements
173    Sequence["_ColumnExpressionArgument[Any]"],
174]
175
176
177_SetupJoinsElement = Tuple[
178    _JoinTargetElement,
179    Optional[_OnClauseElement],
180    Optional["FromClause"],
181    Dict[str, Any],
182]
183
184
185_SelectIterable = Iterable[Union["ColumnElement[Any]", "TextClause"]]
186
187
188class _OffsetLimitParam(BindParameter[int]):
189    inherit_cache = True
190
191    @property
192    def _limit_offset_value(self) -> Optional[int]:
193        return self.effective_value
194
195
196class ReturnsRows(roles.ReturnsRowsRole, DQLDMLClauseElement):
197    """The base-most class for Core constructs that have some concept of
198    columns that can represent rows.
199
200    While the SELECT statement and TABLE are the primary things we think
201    of in this category,  DML like INSERT, UPDATE and DELETE can also specify
202    RETURNING which means they can be used in CTEs and other forms, and
203    PostgreSQL has functions that return rows also.
204
205    .. versionadded:: 1.4
206
207    """
208
209    _is_returns_rows = True
210
211    # sub-elements of returns_rows
212    _is_from_clause = False
213    _is_select_base = False
214    _is_select_statement = False
215    _is_lateral = False
216
217    @property
218    def selectable(self) -> ReturnsRows:
219        return self
220
221    @util.ro_non_memoized_property
222    def _all_selected_columns(self) -> _SelectIterable:
223        """A sequence of column expression objects that represents the
224        "selected" columns of this :class:`_expression.ReturnsRows`.
225
226        This is typically equivalent to .exported_columns except it is
227        delivered in the form of a straight sequence and not  keyed
228        :class:`_expression.ColumnCollection`.
229
230        """
231        raise NotImplementedError()
232
233    def is_derived_from(self, fromclause: Optional[FromClause]) -> bool:
234        """Return ``True`` if this :class:`.ReturnsRows` is
235        'derived' from the given :class:`.FromClause`.
236
237        An example would be an Alias of a Table is derived from that Table.
238
239        """
240        raise NotImplementedError()
241
242    def _generate_fromclause_column_proxies(
243        self, fromclause: FromClause
244    ) -> None:
245        """Populate columns into an :class:`.AliasedReturnsRows` object."""
246
247        raise NotImplementedError()
248
249    def _refresh_for_new_column(self, column: ColumnElement[Any]) -> None:
250        """reset internal collections for an incoming column being added."""
251        raise NotImplementedError()
252
253    @property
254    def exported_columns(self) -> ReadOnlyColumnCollection[Any, Any]:
255        """A :class:`_expression.ColumnCollection`
256        that represents the "exported"
257        columns of this :class:`_expression.ReturnsRows`.
258
259        The "exported" columns represent the collection of
260        :class:`_expression.ColumnElement`
261        expressions that are rendered by this SQL
262        construct.   There are primary varieties which are the
263        "FROM clause columns" of a FROM clause, such as a table, join,
264        or subquery, the "SELECTed columns", which are the columns in
265        the "columns clause" of a SELECT statement, and the RETURNING
266        columns in a DML statement..
267
268        .. versionadded:: 1.4
269
270        .. seealso::
271
272            :attr:`_expression.FromClause.exported_columns`
273
274            :attr:`_expression.SelectBase.exported_columns`
275        """
276
277        raise NotImplementedError()
278
279
280class ExecutableReturnsRows(Executable, ReturnsRows):
281    """base for executable statements that return rows."""
282
283
284class TypedReturnsRows(ExecutableReturnsRows, Generic[_TP]):
285    """base for executable statements that return rows."""
286
287
288class Selectable(ReturnsRows):
289    """Mark a class as being selectable."""
290
291    __visit_name__ = "selectable"
292
293    is_selectable = True
294
295    def _refresh_for_new_column(self, column: ColumnElement[Any]) -> None:
296        raise NotImplementedError()
297
298    def lateral(self, name: Optional[str] = None) -> LateralFromClause:
299        """Return a LATERAL alias of this :class:`_expression.Selectable`.
300
301        The return value is the :class:`_expression.Lateral` construct also
302        provided by the top-level :func:`_expression.lateral` function.
303
304        .. seealso::
305
306            :ref:`tutorial_lateral_correlation` -  overview of usage.
307
308        """
309        return Lateral._construct(self, name=name)
310
311    @util.deprecated(
312        "1.4",
313        message="The :meth:`.Selectable.replace_selectable` method is "
314        "deprecated, and will be removed in a future release.  Similar "
315        "functionality is available via the sqlalchemy.sql.visitors module.",
316    )
317    @util.preload_module("sqlalchemy.sql.util")
318    def replace_selectable(self, old: FromClause, alias: Alias) -> Self:
319        """Replace all occurrences of :class:`_expression.FromClause`
320        'old' with the given :class:`_expression.Alias`
321        object, returning a copy of this :class:`_expression.FromClause`.
322
323        """
324        return util.preloaded.sql_util.ClauseAdapter(alias).traverse(self)
325
326    def corresponding_column(
327        self, column: KeyedColumnElement[Any], require_embedded: bool = False
328    ) -> Optional[KeyedColumnElement[Any]]:
329        """Given a :class:`_expression.ColumnElement`, return the exported
330        :class:`_expression.ColumnElement` object from the
331        :attr:`_expression.Selectable.exported_columns`
332        collection of this :class:`_expression.Selectable`
333        which corresponds to that
334        original :class:`_expression.ColumnElement` via a common ancestor
335        column.
336
337        :param column: the target :class:`_expression.ColumnElement`
338                      to be matched.
339
340        :param require_embedded: only return corresponding columns for
341         the given :class:`_expression.ColumnElement`, if the given
342         :class:`_expression.ColumnElement`
343         is actually present within a sub-element
344         of this :class:`_expression.Selectable`.
345         Normally the column will match if
346         it merely shares a common ancestor with one of the exported
347         columns of this :class:`_expression.Selectable`.
348
349        .. seealso::
350
351            :attr:`_expression.Selectable.exported_columns` - the
352            :class:`_expression.ColumnCollection`
353            that is used for the operation.
354
355            :meth:`_expression.ColumnCollection.corresponding_column`
356            - implementation
357            method.
358
359        """
360
361        return self.exported_columns.corresponding_column(
362            column, require_embedded
363        )
364
365
366class HasPrefixes:
367    _prefixes: Tuple[Tuple[DQLDMLClauseElement, str], ...] = ()
368
369    _has_prefixes_traverse_internals: _TraverseInternalsType = [
370        ("_prefixes", InternalTraversal.dp_prefix_sequence)
371    ]
372
373    @_generative
374    @_document_text_coercion(
375        "prefixes",
376        ":meth:`_expression.HasPrefixes.prefix_with`",
377        ":paramref:`.HasPrefixes.prefix_with.*prefixes`",
378    )
379    def prefix_with(
380        self,
381        *prefixes: _TextCoercedExpressionArgument[Any],
382        dialect: str = "*",
383    ) -> Self:
384        r"""Add one or more expressions following the statement keyword, i.e.
385        SELECT, INSERT, UPDATE, or DELETE. Generative.
386
387        This is used to support backend-specific prefix keywords such as those
388        provided by MySQL.
389
390        E.g.::
391
392            stmt = table.insert().prefix_with("LOW_PRIORITY", dialect="mysql")
393
394            # MySQL 5.7 optimizer hints
395            stmt = select(table).prefix_with(
396                "/*+ BKA(t1) */", dialect="mysql")
397
398        Multiple prefixes can be specified by multiple calls
399        to :meth:`_expression.HasPrefixes.prefix_with`.
400
401        :param \*prefixes: textual or :class:`_expression.ClauseElement`
402         construct which
403         will be rendered following the INSERT, UPDATE, or DELETE
404         keyword.
405        :param dialect: optional string dialect name which will
406         limit rendering of this prefix to only that dialect.
407
408        """
409        self._prefixes = self._prefixes + tuple(
410            [
411                (coercions.expect(roles.StatementOptionRole, p), dialect)
412                for p in prefixes
413            ]
414        )
415        return self
416
417
418class HasSuffixes:
419    _suffixes: Tuple[Tuple[DQLDMLClauseElement, str], ...] = ()
420
421    _has_suffixes_traverse_internals: _TraverseInternalsType = [
422        ("_suffixes", InternalTraversal.dp_prefix_sequence)
423    ]
424
425    @_generative
426    @_document_text_coercion(
427        "suffixes",
428        ":meth:`_expression.HasSuffixes.suffix_with`",
429        ":paramref:`.HasSuffixes.suffix_with.*suffixes`",
430    )
431    def suffix_with(
432        self,
433        *suffixes: _TextCoercedExpressionArgument[Any],
434        dialect: str = "*",
435    ) -> Self:
436        r"""Add one or more expressions following the statement as a whole.
437
438        This is used to support backend-specific suffix keywords on
439        certain constructs.
440
441        E.g.::
442
443            stmt = select(col1, col2).cte().suffix_with(
444                "cycle empno set y_cycle to 1 default 0", dialect="oracle")
445
446        Multiple suffixes can be specified by multiple calls
447        to :meth:`_expression.HasSuffixes.suffix_with`.
448
449        :param \*suffixes: textual or :class:`_expression.ClauseElement`
450         construct which
451         will be rendered following the target clause.
452        :param dialect: Optional string dialect name which will
453         limit rendering of this suffix to only that dialect.
454
455        """
456        self._suffixes = self._suffixes + tuple(
457            [
458                (coercions.expect(roles.StatementOptionRole, p), dialect)
459                for p in suffixes
460            ]
461        )
462        return self
463
464
465class HasHints:
466    _hints: util.immutabledict[Tuple[FromClause, str], str] = (
467        util.immutabledict()
468    )
469    _statement_hints: Tuple[Tuple[str, str], ...] = ()
470
471    _has_hints_traverse_internals: _TraverseInternalsType = [
472        ("_statement_hints", InternalTraversal.dp_statement_hint_list),
473        ("_hints", InternalTraversal.dp_table_hint_list),
474    ]
475
476    def with_statement_hint(self, text: str, dialect_name: str = "*") -> Self:
477        """Add a statement hint to this :class:`_expression.Select` or
478        other selectable object.
479
480        This method is similar to :meth:`_expression.Select.with_hint`
481        except that
482        it does not require an individual table, and instead applies to the
483        statement as a whole.
484
485        Hints here are specific to the backend database and may include
486        directives such as isolation levels, file directives, fetch directives,
487        etc.
488
489        .. seealso::
490
491            :meth:`_expression.Select.with_hint`
492
493            :meth:`_expression.Select.prefix_with` - generic SELECT prefixing
494            which also can suit some database-specific HINT syntaxes such as
495            MySQL optimizer hints
496
497        """
498        return self._with_hint(None, text, dialect_name)
499
500    @_generative
501    def with_hint(
502        self,
503        selectable: _FromClauseArgument,
504        text: str,
505        dialect_name: str = "*",
506    ) -> Self:
507        r"""Add an indexing or other executional context hint for the given
508        selectable to this :class:`_expression.Select` or other selectable
509        object.
510
511        The text of the hint is rendered in the appropriate
512        location for the database backend in use, relative
513        to the given :class:`_schema.Table` or :class:`_expression.Alias`
514        passed as the
515        ``selectable`` argument. The dialect implementation
516        typically uses Python string substitution syntax
517        with the token ``%(name)s`` to render the name of
518        the table or alias. E.g. when using Oracle, the
519        following::
520
521            select(mytable).\
522                with_hint(mytable, "index(%(name)s ix_mytable)")
523
524        Would render SQL as::
525
526            select /*+ index(mytable ix_mytable) */ ... from mytable
527
528        The ``dialect_name`` option will limit the rendering of a particular
529        hint to a particular backend. Such as, to add hints for both Oracle
530        and Sybase simultaneously::
531
532            select(mytable).\
533                with_hint(mytable, "index(%(name)s ix_mytable)", 'oracle').\
534                with_hint(mytable, "WITH INDEX ix_mytable", 'mssql')
535
536        .. seealso::
537
538            :meth:`_expression.Select.with_statement_hint`
539
540        """
541
542        return self._with_hint(selectable, text, dialect_name)
543
544    def _with_hint(
545        self,
546        selectable: Optional[_FromClauseArgument],
547        text: str,
548        dialect_name: str,
549    ) -> Self:
550        if selectable is None:
551            self._statement_hints += ((dialect_name, text),)
552        else:
553            self._hints = self._hints.union(
554                {
555                    (
556                        coercions.expect(roles.FromClauseRole, selectable),
557                        dialect_name,
558                    ): text
559                }
560            )
561        return self
562
563
564class FromClause(roles.AnonymizedFromClauseRole, Selectable):
565    """Represent an element that can be used within the ``FROM``
566    clause of a ``SELECT`` statement.
567
568    The most common forms of :class:`_expression.FromClause` are the
569    :class:`_schema.Table` and the :func:`_expression.select` constructs.  Key
570    features common to all :class:`_expression.FromClause` objects include:
571
572    * a :attr:`.c` collection, which provides per-name access to a collection
573      of :class:`_expression.ColumnElement` objects.
574    * a :attr:`.primary_key` attribute, which is a collection of all those
575      :class:`_expression.ColumnElement`
576      objects that indicate the ``primary_key`` flag.
577    * Methods to generate various derivations of a "from" clause, including
578      :meth:`_expression.FromClause.alias`,
579      :meth:`_expression.FromClause.join`,
580      :meth:`_expression.FromClause.select`.
581
582
583    """
584
585    __visit_name__ = "fromclause"
586    named_with_column = False
587
588    @util.ro_non_memoized_property
589    def _hide_froms(self) -> Iterable[FromClause]:
590        return ()
591
592    _is_clone_of: Optional[FromClause]
593
594    _columns: ColumnCollection[Any, Any]
595
596    schema: Optional[str] = None
597    """Define the 'schema' attribute for this :class:`_expression.FromClause`.
598
599    This is typically ``None`` for most objects except that of
600    :class:`_schema.Table`, where it is taken as the value of the
601    :paramref:`_schema.Table.schema` argument.
602
603    """
604
605    is_selectable = True
606    _is_from_clause = True
607    _is_join = False
608
609    _use_schema_map = False
610
611    def select(self) -> Select[Any]:
612        r"""Return a SELECT of this :class:`_expression.FromClause`.
613
614
615        e.g.::
616
617            stmt = some_table.select().where(some_table.c.id == 5)
618
619        .. seealso::
620
621            :func:`_expression.select` - general purpose
622            method which allows for arbitrary column lists.
623
624        """
625        return Select(self)
626
627    def join(
628        self,
629        right: _FromClauseArgument,
630        onclause: Optional[_ColumnExpressionArgument[bool]] = None,
631        isouter: bool = False,
632        full: bool = False,
633    ) -> Join:
634        """Return a :class:`_expression.Join` from this
635        :class:`_expression.FromClause`
636        to another :class:`FromClause`.
637
638        E.g.::
639
640            from sqlalchemy import join
641
642            j = user_table.join(address_table,
643                            user_table.c.id == address_table.c.user_id)
644            stmt = select(user_table).select_from(j)
645
646        would emit SQL along the lines of::
647
648            SELECT user.id, user.name FROM user
649            JOIN address ON user.id = address.user_id
650
651        :param right: the right side of the join; this is any
652         :class:`_expression.FromClause` object such as a
653         :class:`_schema.Table` object, and
654         may also be a selectable-compatible object such as an ORM-mapped
655         class.
656
657        :param onclause: a SQL expression representing the ON clause of the
658         join.  If left at ``None``, :meth:`_expression.FromClause.join`
659         will attempt to
660         join the two tables based on a foreign key relationship.
661
662        :param isouter: if True, render a LEFT OUTER JOIN, instead of JOIN.
663
664        :param full: if True, render a FULL OUTER JOIN, instead of LEFT OUTER
665         JOIN.  Implies :paramref:`.FromClause.join.isouter`.
666
667        .. seealso::
668
669            :func:`_expression.join` - standalone function
670
671            :class:`_expression.Join` - the type of object produced
672
673        """
674
675        return Join(self, right, onclause, isouter, full)
676
677    def outerjoin(
678        self,
679        right: _FromClauseArgument,
680        onclause: Optional[_ColumnExpressionArgument[bool]] = None,
681        full: bool = False,
682    ) -> Join:
683        """Return a :class:`_expression.Join` from this
684        :class:`_expression.FromClause`
685        to another :class:`FromClause`, with the "isouter" flag set to
686        True.
687
688        E.g.::
689
690            from sqlalchemy import outerjoin
691
692            j = user_table.outerjoin(address_table,
693                            user_table.c.id == address_table.c.user_id)
694
695        The above is equivalent to::
696
697            j = user_table.join(
698                address_table,
699                user_table.c.id == address_table.c.user_id,
700                isouter=True)
701
702        :param right: the right side of the join; this is any
703         :class:`_expression.FromClause` object such as a
704         :class:`_schema.Table` object, and
705         may also be a selectable-compatible object such as an ORM-mapped
706         class.
707
708        :param onclause: a SQL expression representing the ON clause of the
709         join.  If left at ``None``, :meth:`_expression.FromClause.join`
710         will attempt to
711         join the two tables based on a foreign key relationship.
712
713        :param full: if True, render a FULL OUTER JOIN, instead of
714         LEFT OUTER JOIN.
715
716        .. seealso::
717
718            :meth:`_expression.FromClause.join`
719
720            :class:`_expression.Join`
721
722        """
723
724        return Join(self, right, onclause, True, full)
725
726    def alias(
727        self, name: Optional[str] = None, flat: bool = False
728    ) -> NamedFromClause:
729        """Return an alias of this :class:`_expression.FromClause`.
730
731        E.g.::
732
733            a2 = some_table.alias('a2')
734
735        The above code creates an :class:`_expression.Alias`
736        object which can be used
737        as a FROM clause in any SELECT statement.
738
739        .. seealso::
740
741            :ref:`tutorial_using_aliases`
742
743            :func:`_expression.alias`
744
745        """
746
747        return Alias._construct(self, name=name)
748
749    def tablesample(
750        self,
751        sampling: Union[float, Function[Any]],
752        name: Optional[str] = None,
753        seed: Optional[roles.ExpressionElementRole[Any]] = None,
754    ) -> TableSample:
755        """Return a TABLESAMPLE alias of this :class:`_expression.FromClause`.
756
757        The return value is the :class:`_expression.TableSample`
758        construct also
759        provided by the top-level :func:`_expression.tablesample` function.
760
761        .. seealso::
762
763            :func:`_expression.tablesample` - usage guidelines and parameters
764
765        """
766        return TableSample._construct(
767            self, sampling=sampling, name=name, seed=seed
768        )
769
770    def is_derived_from(self, fromclause: Optional[FromClause]) -> bool:
771        """Return ``True`` if this :class:`_expression.FromClause` is
772        'derived' from the given ``FromClause``.
773
774        An example would be an Alias of a Table is derived from that Table.
775
776        """
777        # this is essentially an "identity" check in the base class.
778        # Other constructs override this to traverse through
779        # contained elements.
780        return fromclause in self._cloned_set
781
782    def _is_lexical_equivalent(self, other: FromClause) -> bool:
783        """Return ``True`` if this :class:`_expression.FromClause` and
784        the other represent the same lexical identity.
785
786        This tests if either one is a copy of the other, or
787        if they are the same via annotation identity.
788
789        """
790        return bool(self._cloned_set.intersection(other._cloned_set))
791
792    @util.ro_non_memoized_property
793    def description(self) -> str:
794        """A brief description of this :class:`_expression.FromClause`.
795
796        Used primarily for error message formatting.
797
798        """
799        return getattr(self, "name", self.__class__.__name__ + " object")
800
801    def _generate_fromclause_column_proxies(
802        self, fromclause: FromClause
803    ) -> None:
804        fromclause._columns._populate_separate_keys(
805            col._make_proxy(fromclause) for col in self.c
806        )
807
808    @util.ro_non_memoized_property
809    def exported_columns(
810        self,
811    ) -> ReadOnlyColumnCollection[str, KeyedColumnElement[Any]]:
812        """A :class:`_expression.ColumnCollection`
813        that represents the "exported"
814        columns of this :class:`_expression.Selectable`.
815
816        The "exported" columns for a :class:`_expression.FromClause`
817        object are synonymous
818        with the :attr:`_expression.FromClause.columns` collection.
819
820        .. versionadded:: 1.4
821
822        .. seealso::
823
824            :attr:`_expression.Selectable.exported_columns`
825
826            :attr:`_expression.SelectBase.exported_columns`
827
828
829        """
830        return self.c
831
832    @util.ro_non_memoized_property
833    def columns(
834        self,
835    ) -> ReadOnlyColumnCollection[str, KeyedColumnElement[Any]]:
836        """A named-based collection of :class:`_expression.ColumnElement`
837        objects maintained by this :class:`_expression.FromClause`.
838
839        The :attr:`.columns`, or :attr:`.c` collection, is the gateway
840        to the construction of SQL expressions using table-bound or
841        other selectable-bound columns::
842
843            select(mytable).where(mytable.c.somecolumn == 5)
844
845        :return: a :class:`.ColumnCollection` object.
846
847        """
848        return self.c
849
850    @util.ro_memoized_property
851    def c(self) -> ReadOnlyColumnCollection[str, KeyedColumnElement[Any]]:
852        """
853        A synonym for :attr:`.FromClause.columns`
854
855        :return: a :class:`.ColumnCollection`
856
857        """
858        if "_columns" not in self.__dict__:
859            self._init_collections()
860            self._populate_column_collection()
861        return self._columns.as_readonly()
862
863    @util.ro_non_memoized_property
864    def entity_namespace(self) -> _EntityNamespace:
865        """Return a namespace used for name-based access in SQL expressions.
866
867        This is the namespace that is used to resolve "filter_by()" type
868        expressions, such as::
869
870            stmt.filter_by(address='some address')
871
872        It defaults to the ``.c`` collection, however internally it can
873        be overridden using the "entity_namespace" annotation to deliver
874        alternative results.
875
876        """
877        return self.c
878
879    @util.ro_memoized_property
880    def primary_key(self) -> Iterable[NamedColumn[Any]]:
881        """Return the iterable collection of :class:`_schema.Column` objects
882        which comprise the primary key of this :class:`_selectable.FromClause`.
883
884        For a :class:`_schema.Table` object, this collection is represented
885        by the :class:`_schema.PrimaryKeyConstraint` which itself is an
886        iterable collection of :class:`_schema.Column` objects.
887
888        """
889        self._init_collections()
890        self._populate_column_collection()
891        return self.primary_key
892
893    @util.ro_memoized_property
894    def foreign_keys(self) -> Iterable[ForeignKey]:
895        """Return the collection of :class:`_schema.ForeignKey` marker objects
896        which this FromClause references.
897
898        Each :class:`_schema.ForeignKey` is a member of a
899        :class:`_schema.Table`-wide
900        :class:`_schema.ForeignKeyConstraint`.
901
902        .. seealso::
903
904            :attr:`_schema.Table.foreign_key_constraints`
905
906        """
907        self._init_collections()
908        self._populate_column_collection()
909        return self.foreign_keys
910
911    def _reset_column_collection(self) -> None:
912        """Reset the attributes linked to the ``FromClause.c`` attribute.
913
914        This collection is separate from all the other memoized things
915        as it has shown to be sensitive to being cleared out in situations
916        where enclosing code, typically in a replacement traversal scenario,
917        has already established strong relationships
918        with the exported columns.
919
920        The collection is cleared for the case where a table is having a
921        column added to it as well as within a Join during copy internals.
922
923        """
924
925        for key in ["_columns", "columns", "c", "primary_key", "foreign_keys"]:
926            self.__dict__.pop(key, None)
927
928    @util.ro_non_memoized_property
929    def _select_iterable(self) -> _SelectIterable:
930        return (c for c in self.c if not _never_select_column(c))
931
932    def _init_collections(self) -> None:
933        assert "_columns" not in self.__dict__
934        assert "primary_key" not in self.__dict__
935        assert "foreign_keys" not in self.__dict__
936
937        self._columns = ColumnCollection()
938        self.primary_key = ColumnSet()  # type: ignore
939        self.foreign_keys = set()  # type: ignore
940
941    @property
942    def _cols_populated(self) -> bool:
943        return "_columns" in self.__dict__
944
945    def _populate_column_collection(self) -> None:
946        """Called on subclasses to establish the .c collection.
947
948        Each implementation has a different way of establishing
949        this collection.
950
951        """
952
953    def _refresh_for_new_column(self, column: ColumnElement[Any]) -> None:
954        """Given a column added to the .c collection of an underlying
955        selectable, produce the local version of that column, assuming this
956        selectable ultimately should proxy this column.
957
958        this is used to "ping" a derived selectable to add a new column
959        to its .c. collection when a Column has been added to one of the
960        Table objects it ultimately derives from.
961
962        If the given selectable hasn't populated its .c. collection yet,
963        it should at least pass on the message to the contained selectables,
964        but it will return None.
965
966        This method is currently used by Declarative to allow Table
967        columns to be added to a partially constructed inheritance
968        mapping that may have already produced joins.  The method
969        isn't public right now, as the full span of implications
970        and/or caveats aren't yet clear.
971
972        It's also possible that this functionality could be invoked by
973        default via an event, which would require that
974        selectables maintain a weak referencing collection of all
975        derivations.
976
977        """
978        self._reset_column_collection()
979
980    def _anonymous_fromclause(
981        self, *, name: Optional[str] = None, flat: bool = False
982    ) -> FromClause:
983        return self.alias(name=name)
984
985    if TYPE_CHECKING:
986
987        def self_group(
988            self, against: Optional[OperatorType] = None
989        ) -> Union[FromGrouping, Self]: ...
990
991
992class NamedFromClause(FromClause):
993    """A :class:`.FromClause` that has a name.
994
995    Examples include tables, subqueries, CTEs, aliased tables.
996
997    .. versionadded:: 2.0
998
999    """
1000
1001    named_with_column = True
1002
1003    name: str
1004
1005    @util.preload_module("sqlalchemy.sql.sqltypes")
1006    def table_valued(self) -> TableValuedColumn[Any]:
1007        """Return a :class:`_sql.TableValuedColumn` object for this
1008        :class:`_expression.FromClause`.
1009
1010        A :class:`_sql.TableValuedColumn` is a :class:`_sql.ColumnElement` that
1011        represents a complete row in a table. Support for this construct is
1012        backend dependent, and is supported in various forms by backends
1013        such as PostgreSQL, Oracle and SQL Server.
1014
1015        E.g.:
1016
1017        .. sourcecode:: pycon+sql
1018
1019            >>> from sqlalchemy import select, column, func, table
1020            >>> a = table("a", column("id"), column("x"), column("y"))
1021            >>> stmt = select(func.row_to_json(a.table_valued()))
1022            >>> print(stmt)
1023            {printsql}SELECT row_to_json(a) AS row_to_json_1
1024            FROM a
1025
1026        .. versionadded:: 1.4.0b2
1027
1028        .. seealso::
1029
1030            :ref:`tutorial_functions` - in the :ref:`unified_tutorial`
1031
1032        """
1033        return TableValuedColumn(self, type_api.TABLEVALUE)
1034
1035
1036class SelectLabelStyle(Enum):
1037    """Label style constants that may be passed to
1038    :meth:`_sql.Select.set_label_style`."""
1039
1040    LABEL_STYLE_NONE = 0
1041    """Label style indicating no automatic labeling should be applied to the
1042    columns clause of a SELECT statement.
1043
1044    Below, the columns named ``columna`` are both rendered as is, meaning that
1045    the name ``columna`` can only refer to the first occurrence of this name
1046    within a result set, as well as if the statement were used as a subquery:
1047
1048    .. sourcecode:: pycon+sql
1049
1050        >>> from sqlalchemy import table, column, select, true, LABEL_STYLE_NONE
1051        >>> table1 = table("table1", column("columna"), column("columnb"))
1052        >>> table2 = table("table2", column("columna"), column("columnc"))
1053        >>> print(select(table1, table2).join(table2, true()).set_label_style(LABEL_STYLE_NONE))
1054        {printsql}SELECT table1.columna, table1.columnb, table2.columna, table2.columnc
1055        FROM table1 JOIN table2 ON true
1056
1057    Used with the :meth:`_sql.Select.set_label_style` method.
1058
1059    .. versionadded:: 1.4
1060
1061    """  # noqa: E501
1062
1063    LABEL_STYLE_TABLENAME_PLUS_COL = 1
1064    """Label style indicating all columns should be labeled as
1065    ``<tablename>_<columnname>`` when generating the columns clause of a SELECT
1066    statement, to disambiguate same-named columns referenced from different
1067    tables, aliases, or subqueries.
1068
1069    Below, all column names are given a label so that the two same-named
1070    columns ``columna`` are disambiguated as ``table1_columna`` and
1071    ``table2_columna``:
1072
1073    .. sourcecode:: pycon+sql
1074
1075        >>> from sqlalchemy import table, column, select, true, LABEL_STYLE_TABLENAME_PLUS_COL
1076        >>> table1 = table("table1", column("columna"), column("columnb"))
1077        >>> table2 = table("table2", column("columna"), column("columnc"))
1078        >>> print(select(table1, table2).join(table2, true()).set_label_style(LABEL_STYLE_TABLENAME_PLUS_COL))
1079        {printsql}SELECT table1.columna AS table1_columna, table1.columnb AS table1_columnb, table2.columna AS table2_columna, table2.columnc AS table2_columnc
1080        FROM table1 JOIN table2 ON true
1081
1082    Used with the :meth:`_sql.GenerativeSelect.set_label_style` method.
1083    Equivalent to the legacy method ``Select.apply_labels()``;
1084    :data:`_sql.LABEL_STYLE_TABLENAME_PLUS_COL` is SQLAlchemy's legacy
1085    auto-labeling style. :data:`_sql.LABEL_STYLE_DISAMBIGUATE_ONLY` provides a
1086    less intrusive approach to disambiguation of same-named column expressions.
1087
1088
1089    .. versionadded:: 1.4
1090
1091    """  # noqa: E501
1092
1093    LABEL_STYLE_DISAMBIGUATE_ONLY = 2
1094    """Label style indicating that columns with a name that conflicts with
1095    an existing name should be labeled with a semi-anonymizing label
1096    when generating the columns clause of a SELECT statement.
1097
1098    Below, most column names are left unaffected, except for the second
1099    occurrence of the name ``columna``, which is labeled using the
1100    label ``columna_1`` to disambiguate it from that of ``tablea.columna``:
1101
1102    .. sourcecode:: pycon+sql
1103
1104        >>> from sqlalchemy import table, column, select, true, LABEL_STYLE_DISAMBIGUATE_ONLY
1105        >>> table1 = table("table1", column("columna"), column("columnb"))
1106        >>> table2 = table("table2", column("columna"), column("columnc"))
1107        >>> print(select(table1, table2).join(table2, true()).set_label_style(LABEL_STYLE_DISAMBIGUATE_ONLY))
1108        {printsql}SELECT table1.columna, table1.columnb, table2.columna AS columna_1, table2.columnc
1109        FROM table1 JOIN table2 ON true
1110
1111    Used with the :meth:`_sql.GenerativeSelect.set_label_style` method,
1112    :data:`_sql.LABEL_STYLE_DISAMBIGUATE_ONLY` is the default labeling style
1113    for all SELECT statements outside of :term:`1.x style` ORM queries.
1114
1115    .. versionadded:: 1.4
1116
1117    """  # noqa: E501
1118
1119    LABEL_STYLE_DEFAULT = LABEL_STYLE_DISAMBIGUATE_ONLY
1120    """The default label style, refers to
1121    :data:`_sql.LABEL_STYLE_DISAMBIGUATE_ONLY`.
1122
1123    .. versionadded:: 1.4
1124
1125    """
1126
1127    LABEL_STYLE_LEGACY_ORM = 3
1128
1129
1130(
1131    LABEL_STYLE_NONE,
1132    LABEL_STYLE_TABLENAME_PLUS_COL,
1133    LABEL_STYLE_DISAMBIGUATE_ONLY,
1134    _,
1135) = list(SelectLabelStyle)
1136
1137LABEL_STYLE_DEFAULT = LABEL_STYLE_DISAMBIGUATE_ONLY
1138
1139
1140class Join(roles.DMLTableRole, FromClause):
1141    """Represent a ``JOIN`` construct between two
1142    :class:`_expression.FromClause`
1143    elements.
1144
1145    The public constructor function for :class:`_expression.Join`
1146    is the module-level
1147    :func:`_expression.join()` function, as well as the
1148    :meth:`_expression.FromClause.join` method
1149    of any :class:`_expression.FromClause` (e.g. such as
1150    :class:`_schema.Table`).
1151
1152    .. seealso::
1153
1154        :func:`_expression.join`
1155
1156        :meth:`_expression.FromClause.join`
1157
1158    """
1159
1160    __visit_name__ = "join"
1161
1162    _traverse_internals: _TraverseInternalsType = [
1163        ("left", InternalTraversal.dp_clauseelement),
1164        ("right", InternalTraversal.dp_clauseelement),
1165        ("onclause", InternalTraversal.dp_clauseelement),
1166        ("isouter", InternalTraversal.dp_boolean),
1167        ("full", InternalTraversal.dp_boolean),
1168    ]
1169
1170    _is_join = True
1171
1172    left: FromClause
1173    right: FromClause
1174    onclause: Optional[ColumnElement[bool]]
1175    isouter: bool
1176    full: bool
1177
1178    def __init__(
1179        self,
1180        left: _FromClauseArgument,
1181        right: _FromClauseArgument,
1182        onclause: Optional[_OnClauseArgument] = None,
1183        isouter: bool = False,
1184        full: bool = False,
1185    ):
1186        """Construct a new :class:`_expression.Join`.
1187
1188        The usual entrypoint here is the :func:`_expression.join`
1189        function or the :meth:`_expression.FromClause.join` method of any
1190        :class:`_expression.FromClause` object.
1191
1192        """
1193
1194        # when deannotate was removed here, callcounts went up for ORM
1195        # compilation of eager joins, since there were more comparisons of
1196        # annotated objects.   test_orm.py -> test_fetch_results
1197        # was therefore changed to show a more real-world use case, where the
1198        # compilation is cached; there's no change in post-cache callcounts.
1199        # callcounts for a single compilation in that particular test
1200        # that includes about eight joins about 1100 extra fn calls, from

Showing the first 1,200 of 6933 lines. Download the file for the rest.

codekingpro/portable-devtools · Team Ai