Update 2025-04-13_16:25:39
This commit is contained in:
145
venv/lib/python3.11/site-packages/sqlalchemy/sql/__init__.py
Normal file
145
venv/lib/python3.11/site-packages/sqlalchemy/sql/__init__.py
Normal file
@ -0,0 +1,145 @@
|
||||
# sql/__init__.py
|
||||
# Copyright (C) 2005-2025 the SQLAlchemy authors and contributors
|
||||
# <see AUTHORS file>
|
||||
#
|
||||
# This module is part of SQLAlchemy and is released under
|
||||
# the MIT License: https://www.opensource.org/licenses/mit-license.php
|
||||
from typing import Any
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from ._typing import ColumnExpressionArgument as ColumnExpressionArgument
|
||||
from ._typing import NotNullable as NotNullable
|
||||
from ._typing import Nullable as Nullable
|
||||
from .base import Executable as Executable
|
||||
from .compiler import COLLECT_CARTESIAN_PRODUCTS as COLLECT_CARTESIAN_PRODUCTS
|
||||
from .compiler import FROM_LINTING as FROM_LINTING
|
||||
from .compiler import NO_LINTING as NO_LINTING
|
||||
from .compiler import WARN_LINTING as WARN_LINTING
|
||||
from .ddl import BaseDDLElement as BaseDDLElement
|
||||
from .ddl import DDL as DDL
|
||||
from .ddl import DDLElement as DDLElement
|
||||
from .ddl import ExecutableDDLElement as ExecutableDDLElement
|
||||
from .expression import Alias as Alias
|
||||
from .expression import alias as alias
|
||||
from .expression import all_ as all_
|
||||
from .expression import and_ as and_
|
||||
from .expression import any_ as any_
|
||||
from .expression import asc as asc
|
||||
from .expression import between as between
|
||||
from .expression import bindparam as bindparam
|
||||
from .expression import case as case
|
||||
from .expression import cast as cast
|
||||
from .expression import ClauseElement as ClauseElement
|
||||
from .expression import collate as collate
|
||||
from .expression import column as column
|
||||
from .expression import ColumnCollection as ColumnCollection
|
||||
from .expression import ColumnElement as ColumnElement
|
||||
from .expression import CompoundSelect as CompoundSelect
|
||||
from .expression import cte as cte
|
||||
from .expression import Delete as Delete
|
||||
from .expression import delete as delete
|
||||
from .expression import desc as desc
|
||||
from .expression import distinct as distinct
|
||||
from .expression import except_ as except_
|
||||
from .expression import except_all as except_all
|
||||
from .expression import exists as exists
|
||||
from .expression import extract as extract
|
||||
from .expression import false as false
|
||||
from .expression import False_ as False_
|
||||
from .expression import FromClause as FromClause
|
||||
from .expression import func as func
|
||||
from .expression import funcfilter as funcfilter
|
||||
from .expression import Insert as Insert
|
||||
from .expression import insert as insert
|
||||
from .expression import intersect as intersect
|
||||
from .expression import intersect_all as intersect_all
|
||||
from .expression import Join as Join
|
||||
from .expression import join as join
|
||||
from .expression import label as label
|
||||
from .expression import LABEL_STYLE_DEFAULT as LABEL_STYLE_DEFAULT
|
||||
from .expression import (
|
||||
LABEL_STYLE_DISAMBIGUATE_ONLY as LABEL_STYLE_DISAMBIGUATE_ONLY,
|
||||
)
|
||||
from .expression import LABEL_STYLE_NONE as LABEL_STYLE_NONE
|
||||
from .expression import (
|
||||
LABEL_STYLE_TABLENAME_PLUS_COL as LABEL_STYLE_TABLENAME_PLUS_COL,
|
||||
)
|
||||
from .expression import lambda_stmt as lambda_stmt
|
||||
from .expression import LambdaElement as LambdaElement
|
||||
from .expression import lateral as lateral
|
||||
from .expression import literal as literal
|
||||
from .expression import literal_column as literal_column
|
||||
from .expression import modifier as modifier
|
||||
from .expression import not_ as not_
|
||||
from .expression import null as null
|
||||
from .expression import nulls_first as nulls_first
|
||||
from .expression import nulls_last as nulls_last
|
||||
from .expression import nullsfirst as nullsfirst
|
||||
from .expression import nullslast as nullslast
|
||||
from .expression import or_ as or_
|
||||
from .expression import outerjoin as outerjoin
|
||||
from .expression import outparam as outparam
|
||||
from .expression import over as over
|
||||
from .expression import quoted_name as quoted_name
|
||||
from .expression import Select as Select
|
||||
from .expression import select as select
|
||||
from .expression import Selectable as Selectable
|
||||
from .expression import SelectLabelStyle as SelectLabelStyle
|
||||
from .expression import SQLColumnExpression as SQLColumnExpression
|
||||
from .expression import StatementLambdaElement as StatementLambdaElement
|
||||
from .expression import Subquery as Subquery
|
||||
from .expression import table as table
|
||||
from .expression import TableClause as TableClause
|
||||
from .expression import TableSample as TableSample
|
||||
from .expression import tablesample as tablesample
|
||||
from .expression import text as text
|
||||
from .expression import true as true
|
||||
from .expression import True_ as True_
|
||||
from .expression import try_cast as try_cast
|
||||
from .expression import tuple_ as tuple_
|
||||
from .expression import type_coerce as type_coerce
|
||||
from .expression import union as union
|
||||
from .expression import union_all as union_all
|
||||
from .expression import Update as Update
|
||||
from .expression import update as update
|
||||
from .expression import Values as Values
|
||||
from .expression import values as values
|
||||
from .expression import within_group as within_group
|
||||
from .visitors import ClauseVisitor as ClauseVisitor
|
||||
|
||||
|
||||
def __go(lcls: Any) -> None:
|
||||
from .. import util as _sa_util
|
||||
|
||||
from . import base
|
||||
from . import coercions
|
||||
from . import elements
|
||||
from . import lambdas
|
||||
from . import selectable
|
||||
from . import schema
|
||||
from . import traversals
|
||||
from . import type_api
|
||||
|
||||
if not TYPE_CHECKING:
|
||||
base.coercions = elements.coercions = coercions
|
||||
base.elements = elements
|
||||
base.type_api = type_api
|
||||
coercions.elements = elements
|
||||
coercions.lambdas = lambdas
|
||||
coercions.schema = schema
|
||||
coercions.selectable = selectable
|
||||
|
||||
from .annotation import _prepare_annotations
|
||||
from .annotation import Annotated
|
||||
from .elements import AnnotatedColumnElement
|
||||
from .elements import ClauseList
|
||||
from .selectable import AnnotatedFromClause
|
||||
|
||||
_prepare_annotations(ColumnElement, AnnotatedColumnElement)
|
||||
_prepare_annotations(FromClause, AnnotatedFromClause)
|
||||
_prepare_annotations(ClauseList, Annotated)
|
||||
|
||||
_sa_util.preloaded.import_prefix("sqlalchemy.sql")
|
||||
|
||||
|
||||
__go(locals())
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,132 @@
|
||||
# sql/_dml_constructors.py
|
||||
# Copyright (C) 2005-2025 the SQLAlchemy authors and contributors
|
||||
# <see AUTHORS file>
|
||||
#
|
||||
# This module is part of SQLAlchemy and is released under
|
||||
# the MIT License: https://www.opensource.org/licenses/mit-license.php
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from .dml import Delete
|
||||
from .dml import Insert
|
||||
from .dml import Update
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from ._typing import _DMLTableArgument
|
||||
|
||||
|
||||
def insert(table: _DMLTableArgument) -> Insert:
|
||||
"""Construct an :class:`_expression.Insert` object.
|
||||
|
||||
E.g.::
|
||||
|
||||
from sqlalchemy import insert
|
||||
|
||||
stmt = insert(user_table).values(name="username", fullname="Full Username")
|
||||
|
||||
Similar functionality is available via the
|
||||
:meth:`_expression.TableClause.insert` method on
|
||||
:class:`_schema.Table`.
|
||||
|
||||
.. seealso::
|
||||
|
||||
:ref:`tutorial_core_insert` - in the :ref:`unified_tutorial`
|
||||
|
||||
|
||||
:param table: :class:`_expression.TableClause`
|
||||
which is the subject of the
|
||||
insert.
|
||||
|
||||
:param values: collection of values to be inserted; see
|
||||
:meth:`_expression.Insert.values`
|
||||
for a description of allowed formats here.
|
||||
Can be omitted entirely; a :class:`_expression.Insert` construct
|
||||
will also dynamically render the VALUES clause at execution time
|
||||
based on the parameters passed to :meth:`_engine.Connection.execute`.
|
||||
|
||||
:param inline: if True, no attempt will be made to retrieve the
|
||||
SQL-generated default values to be provided within the statement;
|
||||
in particular,
|
||||
this allows SQL expressions to be rendered 'inline' within the
|
||||
statement without the need to pre-execute them beforehand; for
|
||||
backends that support "returning", this turns off the "implicit
|
||||
returning" feature for the statement.
|
||||
|
||||
If both :paramref:`_expression.insert.values` and compile-time bind
|
||||
parameters are present, the compile-time bind parameters override the
|
||||
information specified within :paramref:`_expression.insert.values` on a
|
||||
per-key basis.
|
||||
|
||||
The keys within :paramref:`_expression.Insert.values` can be either
|
||||
:class:`~sqlalchemy.schema.Column` objects or their string
|
||||
identifiers. Each key may reference one of:
|
||||
|
||||
* a literal data value (i.e. string, number, etc.);
|
||||
* a Column object;
|
||||
* a SELECT statement.
|
||||
|
||||
If a ``SELECT`` statement is specified which references this
|
||||
``INSERT`` statement's table, the statement will be correlated
|
||||
against the ``INSERT`` statement.
|
||||
|
||||
.. seealso::
|
||||
|
||||
:ref:`tutorial_core_insert` - in the :ref:`unified_tutorial`
|
||||
|
||||
""" # noqa: E501
|
||||
return Insert(table)
|
||||
|
||||
|
||||
def update(table: _DMLTableArgument) -> Update:
|
||||
r"""Construct an :class:`_expression.Update` object.
|
||||
|
||||
E.g.::
|
||||
|
||||
from sqlalchemy import update
|
||||
|
||||
stmt = (
|
||||
update(user_table).where(user_table.c.id == 5).values(name="user #5")
|
||||
)
|
||||
|
||||
Similar functionality is available via the
|
||||
:meth:`_expression.TableClause.update` method on
|
||||
:class:`_schema.Table`.
|
||||
|
||||
:param table: A :class:`_schema.Table`
|
||||
object representing the database
|
||||
table to be updated.
|
||||
|
||||
|
||||
.. seealso::
|
||||
|
||||
:ref:`tutorial_core_update_delete` - in the :ref:`unified_tutorial`
|
||||
|
||||
|
||||
""" # noqa: E501
|
||||
return Update(table)
|
||||
|
||||
|
||||
def delete(table: _DMLTableArgument) -> Delete:
|
||||
r"""Construct :class:`_expression.Delete` object.
|
||||
|
||||
E.g.::
|
||||
|
||||
from sqlalchemy import delete
|
||||
|
||||
stmt = delete(user_table).where(user_table.c.id == 5)
|
||||
|
||||
Similar functionality is available via the
|
||||
:meth:`_expression.TableClause.delete` method on
|
||||
:class:`_schema.Table`.
|
||||
|
||||
:param table: The table to delete rows from.
|
||||
|
||||
.. seealso::
|
||||
|
||||
:ref:`tutorial_core_update_delete` - in the :ref:`unified_tutorial`
|
||||
|
||||
|
||||
"""
|
||||
return Delete(table)
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,20 @@
|
||||
# sql/_orm_types.py
|
||||
# Copyright (C) 2022-2025 the SQLAlchemy authors and contributors
|
||||
# <see AUTHORS file>
|
||||
#
|
||||
# This module is part of SQLAlchemy and is released under
|
||||
# the MIT License: https://www.opensource.org/licenses/mit-license.php
|
||||
|
||||
"""ORM types that need to present specifically for **documentation only** of
|
||||
the Executable.execution_options() method, which includes options that
|
||||
are meaningful to the ORM.
|
||||
|
||||
"""
|
||||
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from ..util.typing import Literal
|
||||
|
||||
SynchronizeSessionArgument = Literal[False, "auto", "evaluate", "fetch"]
|
||||
DMLStrategyArgument = Literal["bulk", "raw", "orm", "auto"]
|
75
venv/lib/python3.11/site-packages/sqlalchemy/sql/_py_util.py
Normal file
75
venv/lib/python3.11/site-packages/sqlalchemy/sql/_py_util.py
Normal file
@ -0,0 +1,75 @@
|
||||
# sql/_py_util.py
|
||||
# Copyright (C) 2005-2025 the SQLAlchemy authors and contributors
|
||||
# <see AUTHORS file>
|
||||
#
|
||||
# This module is part of SQLAlchemy and is released under
|
||||
# the MIT License: https://www.opensource.org/licenses/mit-license.php
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import typing
|
||||
from typing import Any
|
||||
from typing import Dict
|
||||
from typing import Tuple
|
||||
from typing import Union
|
||||
|
||||
from ..util.typing import Literal
|
||||
|
||||
if typing.TYPE_CHECKING:
|
||||
from .cache_key import CacheConst
|
||||
|
||||
|
||||
class prefix_anon_map(Dict[str, str]):
|
||||
"""A map that creates new keys for missing key access.
|
||||
|
||||
Considers keys of the form "<ident> <name>" to produce
|
||||
new symbols "<name>_<index>", where "index" is an incrementing integer
|
||||
corresponding to <name>.
|
||||
|
||||
Inlines the approach taken by :class:`sqlalchemy.util.PopulateDict` which
|
||||
is otherwise usually used for this type of operation.
|
||||
|
||||
"""
|
||||
|
||||
def __missing__(self, key: str) -> str:
|
||||
(ident, derived) = key.split(" ", 1)
|
||||
anonymous_counter = self.get(derived, 1)
|
||||
self[derived] = anonymous_counter + 1 # type: ignore
|
||||
value = f"{derived}_{anonymous_counter}"
|
||||
self[key] = value
|
||||
return value
|
||||
|
||||
|
||||
class cache_anon_map(
|
||||
Dict[Union[int, "Literal[CacheConst.NO_CACHE]"], Union[Literal[True], str]]
|
||||
):
|
||||
"""A map that creates new keys for missing key access.
|
||||
|
||||
Produces an incrementing sequence given a series of unique keys.
|
||||
|
||||
This is similar to the compiler prefix_anon_map class although simpler.
|
||||
|
||||
Inlines the approach taken by :class:`sqlalchemy.util.PopulateDict` which
|
||||
is otherwise usually used for this type of operation.
|
||||
|
||||
"""
|
||||
|
||||
_index = 0
|
||||
|
||||
def get_anon(self, object_: Any) -> Tuple[str, bool]:
|
||||
idself = id(object_)
|
||||
if idself in self:
|
||||
s_val = self[idself]
|
||||
assert s_val is not True
|
||||
return s_val, True
|
||||
else:
|
||||
# inline of __missing__
|
||||
self[idself] = id_ = str(self._index)
|
||||
self._index += 1
|
||||
|
||||
return id_, False
|
||||
|
||||
def __missing__(self, key: int) -> str:
|
||||
self[key] = val = str(self._index)
|
||||
self._index += 1
|
||||
return val
|
@ -0,0 +1,715 @@
|
||||
# sql/_selectable_constructors.py
|
||||
# Copyright (C) 2005-2025 the SQLAlchemy authors and contributors
|
||||
# <see AUTHORS file>
|
||||
#
|
||||
# This module is part of SQLAlchemy and is released under
|
||||
# the MIT License: https://www.opensource.org/licenses/mit-license.php
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
from typing import Optional
|
||||
from typing import overload
|
||||
from typing import Tuple
|
||||
from typing import TYPE_CHECKING
|
||||
from typing import Union
|
||||
|
||||
from . import coercions
|
||||
from . import roles
|
||||
from ._typing import _ColumnsClauseArgument
|
||||
from ._typing import _no_kw
|
||||
from .elements import ColumnClause
|
||||
from .selectable import Alias
|
||||
from .selectable import CompoundSelect
|
||||
from .selectable import Exists
|
||||
from .selectable import FromClause
|
||||
from .selectable import Join
|
||||
from .selectable import Lateral
|
||||
from .selectable import LateralFromClause
|
||||
from .selectable import NamedFromClause
|
||||
from .selectable import Select
|
||||
from .selectable import TableClause
|
||||
from .selectable import TableSample
|
||||
from .selectable import Values
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from ._typing import _FromClauseArgument
|
||||
from ._typing import _OnClauseArgument
|
||||
from ._typing import _SelectStatementForCompoundArgument
|
||||
from ._typing import _T0
|
||||
from ._typing import _T1
|
||||
from ._typing import _T2
|
||||
from ._typing import _T3
|
||||
from ._typing import _T4
|
||||
from ._typing import _T5
|
||||
from ._typing import _T6
|
||||
from ._typing import _T7
|
||||
from ._typing import _T8
|
||||
from ._typing import _T9
|
||||
from ._typing import _TP
|
||||
from ._typing import _TypedColumnClauseArgument as _TCCA
|
||||
from .functions import Function
|
||||
from .selectable import CTE
|
||||
from .selectable import HasCTE
|
||||
from .selectable import ScalarSelect
|
||||
from .selectable import SelectBase
|
||||
|
||||
|
||||
def alias(
|
||||
selectable: FromClause, name: Optional[str] = None, flat: bool = False
|
||||
) -> NamedFromClause:
|
||||
"""Return a named alias of the given :class:`.FromClause`.
|
||||
|
||||
For :class:`.Table` and :class:`.Join` objects, the return type is the
|
||||
:class:`_expression.Alias` object. Other kinds of :class:`.NamedFromClause`
|
||||
objects may be returned for other kinds of :class:`.FromClause` objects.
|
||||
|
||||
The named alias represents any :class:`_expression.FromClause` with an
|
||||
alternate name assigned within SQL, typically using the ``AS`` clause when
|
||||
generated, e.g. ``SELECT * FROM table AS aliasname``.
|
||||
|
||||
Equivalent functionality is available via the
|
||||
:meth:`_expression.FromClause.alias`
|
||||
method available on all :class:`_expression.FromClause` objects.
|
||||
|
||||
:param selectable: any :class:`_expression.FromClause` subclass,
|
||||
such as a table, select statement, etc.
|
||||
|
||||
:param name: string name to be assigned as the alias.
|
||||
If ``None``, a name will be deterministically generated at compile
|
||||
time. Deterministic means the name is guaranteed to be unique against
|
||||
other constructs used in the same statement, and will also be the same
|
||||
name for each successive compilation of the same statement object.
|
||||
|
||||
:param flat: Will be passed through to if the given selectable
|
||||
is an instance of :class:`_expression.Join` - see
|
||||
:meth:`_expression.Join.alias` for details.
|
||||
|
||||
"""
|
||||
return Alias._factory(selectable, name=name, flat=flat)
|
||||
|
||||
|
||||
def cte(
|
||||
selectable: HasCTE, name: Optional[str] = None, recursive: bool = False
|
||||
) -> CTE:
|
||||
r"""Return a new :class:`_expression.CTE`,
|
||||
or Common Table Expression instance.
|
||||
|
||||
Please see :meth:`_expression.HasCTE.cte` for detail on CTE usage.
|
||||
|
||||
"""
|
||||
return coercions.expect(roles.HasCTERole, selectable).cte(
|
||||
name=name, recursive=recursive
|
||||
)
|
||||
|
||||
|
||||
# TODO: mypy requires the _TypedSelectable overloads in all compound select
|
||||
# constructors since _SelectStatementForCompoundArgument includes
|
||||
# untyped args that make it return CompoundSelect[Unpack[tuple[Never, ...]]]
|
||||
# pyright does not have this issue
|
||||
_TypedSelectable = Union["Select[_TP]", "CompoundSelect[_TP]"]
|
||||
|
||||
|
||||
@overload
|
||||
def except_(
|
||||
*selects: _TypedSelectable[_TP],
|
||||
) -> CompoundSelect[_TP]: ...
|
||||
|
||||
|
||||
@overload
|
||||
def except_(
|
||||
*selects: _SelectStatementForCompoundArgument[_TP],
|
||||
) -> CompoundSelect[_TP]: ...
|
||||
|
||||
|
||||
def except_(
|
||||
*selects: _SelectStatementForCompoundArgument[_TP],
|
||||
) -> CompoundSelect[_TP]:
|
||||
r"""Return an ``EXCEPT`` of multiple selectables.
|
||||
|
||||
The returned object is an instance of
|
||||
:class:`_expression.CompoundSelect`.
|
||||
|
||||
:param \*selects:
|
||||
a list of :class:`_expression.Select` instances.
|
||||
|
||||
"""
|
||||
return CompoundSelect._create_except(*selects)
|
||||
|
||||
|
||||
@overload
|
||||
def except_all(
|
||||
*selects: _TypedSelectable[_TP],
|
||||
) -> CompoundSelect[_TP]: ...
|
||||
|
||||
|
||||
@overload
|
||||
def except_all(
|
||||
*selects: _SelectStatementForCompoundArgument[_TP],
|
||||
) -> CompoundSelect[_TP]: ...
|
||||
|
||||
|
||||
def except_all(
|
||||
*selects: _SelectStatementForCompoundArgument[_TP],
|
||||
) -> CompoundSelect[_TP]:
|
||||
r"""Return an ``EXCEPT ALL`` of multiple selectables.
|
||||
|
||||
The returned object is an instance of
|
||||
:class:`_expression.CompoundSelect`.
|
||||
|
||||
:param \*selects:
|
||||
a list of :class:`_expression.Select` instances.
|
||||
|
||||
"""
|
||||
return CompoundSelect._create_except_all(*selects)
|
||||
|
||||
|
||||
def exists(
|
||||
__argument: Optional[
|
||||
Union[_ColumnsClauseArgument[Any], SelectBase, ScalarSelect[Any]]
|
||||
] = None,
|
||||
) -> Exists:
|
||||
"""Construct a new :class:`_expression.Exists` construct.
|
||||
|
||||
The :func:`_sql.exists` can be invoked by itself to produce an
|
||||
:class:`_sql.Exists` construct, which will accept simple WHERE
|
||||
criteria::
|
||||
|
||||
exists_criteria = exists().where(table1.c.col1 == table2.c.col2)
|
||||
|
||||
However, for greater flexibility in constructing the SELECT, an
|
||||
existing :class:`_sql.Select` construct may be converted to an
|
||||
:class:`_sql.Exists`, most conveniently by making use of the
|
||||
:meth:`_sql.SelectBase.exists` method::
|
||||
|
||||
exists_criteria = (
|
||||
select(table2.c.col2).where(table1.c.col1 == table2.c.col2).exists()
|
||||
)
|
||||
|
||||
The EXISTS criteria is then used inside of an enclosing SELECT::
|
||||
|
||||
stmt = select(table1.c.col1).where(exists_criteria)
|
||||
|
||||
The above statement will then be of the form:
|
||||
|
||||
.. sourcecode:: sql
|
||||
|
||||
SELECT col1 FROM table1 WHERE EXISTS
|
||||
(SELECT table2.col2 FROM table2 WHERE table2.col2 = table1.col1)
|
||||
|
||||
.. seealso::
|
||||
|
||||
:ref:`tutorial_exists` - in the :term:`2.0 style` tutorial.
|
||||
|
||||
:meth:`_sql.SelectBase.exists` - method to transform a ``SELECT`` to an
|
||||
``EXISTS`` clause.
|
||||
|
||||
""" # noqa: E501
|
||||
|
||||
return Exists(__argument)
|
||||
|
||||
|
||||
@overload
|
||||
def intersect(
|
||||
*selects: _TypedSelectable[_TP],
|
||||
) -> CompoundSelect[_TP]: ...
|
||||
|
||||
|
||||
@overload
|
||||
def intersect(
|
||||
*selects: _SelectStatementForCompoundArgument[_TP],
|
||||
) -> CompoundSelect[_TP]: ...
|
||||
|
||||
|
||||
def intersect(
|
||||
*selects: _SelectStatementForCompoundArgument[_TP],
|
||||
) -> CompoundSelect[_TP]:
|
||||
r"""Return an ``INTERSECT`` of multiple selectables.
|
||||
|
||||
The returned object is an instance of
|
||||
:class:`_expression.CompoundSelect`.
|
||||
|
||||
:param \*selects:
|
||||
a list of :class:`_expression.Select` instances.
|
||||
|
||||
"""
|
||||
return CompoundSelect._create_intersect(*selects)
|
||||
|
||||
|
||||
@overload
|
||||
def intersect_all(
|
||||
*selects: _TypedSelectable[_TP],
|
||||
) -> CompoundSelect[_TP]: ...
|
||||
|
||||
|
||||
@overload
|
||||
def intersect_all(
|
||||
*selects: _SelectStatementForCompoundArgument[_TP],
|
||||
) -> CompoundSelect[_TP]: ...
|
||||
|
||||
|
||||
def intersect_all(
|
||||
*selects: _SelectStatementForCompoundArgument[_TP],
|
||||
) -> CompoundSelect[_TP]:
|
||||
r"""Return an ``INTERSECT ALL`` of multiple selectables.
|
||||
|
||||
The returned object is an instance of
|
||||
:class:`_expression.CompoundSelect`.
|
||||
|
||||
:param \*selects:
|
||||
a list of :class:`_expression.Select` instances.
|
||||
|
||||
|
||||
"""
|
||||
return CompoundSelect._create_intersect_all(*selects)
|
||||
|
||||
|
||||
def join(
|
||||
left: _FromClauseArgument,
|
||||
right: _FromClauseArgument,
|
||||
onclause: Optional[_OnClauseArgument] = None,
|
||||
isouter: bool = False,
|
||||
full: bool = False,
|
||||
) -> Join:
|
||||
"""Produce a :class:`_expression.Join` object, given two
|
||||
:class:`_expression.FromClause`
|
||||
expressions.
|
||||
|
||||
E.g.::
|
||||
|
||||
j = join(
|
||||
user_table, address_table, user_table.c.id == address_table.c.user_id
|
||||
)
|
||||
stmt = select(user_table).select_from(j)
|
||||
|
||||
would emit SQL along the lines of:
|
||||
|
||||
.. sourcecode:: sql
|
||||
|
||||
SELECT user.id, user.name FROM user
|
||||
JOIN address ON user.id = address.user_id
|
||||
|
||||
Similar functionality is available given any
|
||||
:class:`_expression.FromClause` object (e.g. such as a
|
||||
:class:`_schema.Table`) using
|
||||
the :meth:`_expression.FromClause.join` method.
|
||||
|
||||
:param left: The left side of the join.
|
||||
|
||||
:param right: the right side of the join; this is any
|
||||
:class:`_expression.FromClause` object such as a
|
||||
:class:`_schema.Table` object, and
|
||||
may also be a selectable-compatible object such as an ORM-mapped
|
||||
class.
|
||||
|
||||
:param onclause: a SQL expression representing the ON clause of the
|
||||
join. If left at ``None``, :meth:`_expression.FromClause.join`
|
||||
will attempt to
|
||||
join the two tables based on a foreign key relationship.
|
||||
|
||||
:param isouter: if True, render a LEFT OUTER JOIN, instead of JOIN.
|
||||
|
||||
:param full: if True, render a FULL OUTER JOIN, instead of JOIN.
|
||||
|
||||
.. seealso::
|
||||
|
||||
:meth:`_expression.FromClause.join` - method form,
|
||||
based on a given left side.
|
||||
|
||||
:class:`_expression.Join` - the type of object produced.
|
||||
|
||||
""" # noqa: E501
|
||||
|
||||
return Join(left, right, onclause, isouter, full)
|
||||
|
||||
|
||||
def lateral(
|
||||
selectable: Union[SelectBase, _FromClauseArgument],
|
||||
name: Optional[str] = None,
|
||||
) -> LateralFromClause:
|
||||
"""Return a :class:`_expression.Lateral` object.
|
||||
|
||||
:class:`_expression.Lateral` is an :class:`_expression.Alias`
|
||||
subclass that represents
|
||||
a subquery with the LATERAL keyword applied to it.
|
||||
|
||||
The special behavior of a LATERAL subquery is that it appears in the
|
||||
FROM clause of an enclosing SELECT, but may correlate to other
|
||||
FROM clauses of that SELECT. It is a special case of subquery
|
||||
only supported by a small number of backends, currently more recent
|
||||
PostgreSQL versions.
|
||||
|
||||
.. seealso::
|
||||
|
||||
:ref:`tutorial_lateral_correlation` - overview of usage.
|
||||
|
||||
"""
|
||||
return Lateral._factory(selectable, name=name)
|
||||
|
||||
|
||||
def outerjoin(
|
||||
left: _FromClauseArgument,
|
||||
right: _FromClauseArgument,
|
||||
onclause: Optional[_OnClauseArgument] = None,
|
||||
full: bool = False,
|
||||
) -> Join:
|
||||
"""Return an ``OUTER JOIN`` clause element.
|
||||
|
||||
The returned object is an instance of :class:`_expression.Join`.
|
||||
|
||||
Similar functionality is also available via the
|
||||
:meth:`_expression.FromClause.outerjoin` method on any
|
||||
:class:`_expression.FromClause`.
|
||||
|
||||
:param left: The left side of the join.
|
||||
|
||||
:param right: The right side of the join.
|
||||
|
||||
:param onclause: Optional criterion for the ``ON`` clause, is
|
||||
derived from foreign key relationships established between
|
||||
left and right otherwise.
|
||||
|
||||
To chain joins together, use the :meth:`_expression.FromClause.join`
|
||||
or
|
||||
:meth:`_expression.FromClause.outerjoin` methods on the resulting
|
||||
:class:`_expression.Join` object.
|
||||
|
||||
"""
|
||||
return Join(left, right, onclause, isouter=True, full=full)
|
||||
|
||||
|
||||
# START OVERLOADED FUNCTIONS select Select 1-10
|
||||
|
||||
# code within this block is **programmatically,
|
||||
# statically generated** by tools/generate_tuple_map_overloads.py
|
||||
|
||||
|
||||
@overload
|
||||
def select(__ent0: _TCCA[_T0]) -> Select[Tuple[_T0]]: ...
|
||||
|
||||
|
||||
@overload
|
||||
def select(
|
||||
__ent0: _TCCA[_T0], __ent1: _TCCA[_T1]
|
||||
) -> Select[Tuple[_T0, _T1]]: ...
|
||||
|
||||
|
||||
@overload
|
||||
def select(
|
||||
__ent0: _TCCA[_T0], __ent1: _TCCA[_T1], __ent2: _TCCA[_T2]
|
||||
) -> Select[Tuple[_T0, _T1, _T2]]: ...
|
||||
|
||||
|
||||
@overload
|
||||
def select(
|
||||
__ent0: _TCCA[_T0],
|
||||
__ent1: _TCCA[_T1],
|
||||
__ent2: _TCCA[_T2],
|
||||
__ent3: _TCCA[_T3],
|
||||
) -> Select[Tuple[_T0, _T1, _T2, _T3]]: ...
|
||||
|
||||
|
||||
@overload
|
||||
def select(
|
||||
__ent0: _TCCA[_T0],
|
||||
__ent1: _TCCA[_T1],
|
||||
__ent2: _TCCA[_T2],
|
||||
__ent3: _TCCA[_T3],
|
||||
__ent4: _TCCA[_T4],
|
||||
) -> Select[Tuple[_T0, _T1, _T2, _T3, _T4]]: ...
|
||||
|
||||
|
||||
@overload
|
||||
def select(
|
||||
__ent0: _TCCA[_T0],
|
||||
__ent1: _TCCA[_T1],
|
||||
__ent2: _TCCA[_T2],
|
||||
__ent3: _TCCA[_T3],
|
||||
__ent4: _TCCA[_T4],
|
||||
__ent5: _TCCA[_T5],
|
||||
) -> Select[Tuple[_T0, _T1, _T2, _T3, _T4, _T5]]: ...
|
||||
|
||||
|
||||
@overload
|
||||
def select(
|
||||
__ent0: _TCCA[_T0],
|
||||
__ent1: _TCCA[_T1],
|
||||
__ent2: _TCCA[_T2],
|
||||
__ent3: _TCCA[_T3],
|
||||
__ent4: _TCCA[_T4],
|
||||
__ent5: _TCCA[_T5],
|
||||
__ent6: _TCCA[_T6],
|
||||
) -> Select[Tuple[_T0, _T1, _T2, _T3, _T4, _T5, _T6]]: ...
|
||||
|
||||
|
||||
@overload
|
||||
def select(
|
||||
__ent0: _TCCA[_T0],
|
||||
__ent1: _TCCA[_T1],
|
||||
__ent2: _TCCA[_T2],
|
||||
__ent3: _TCCA[_T3],
|
||||
__ent4: _TCCA[_T4],
|
||||
__ent5: _TCCA[_T5],
|
||||
__ent6: _TCCA[_T6],
|
||||
__ent7: _TCCA[_T7],
|
||||
) -> Select[Tuple[_T0, _T1, _T2, _T3, _T4, _T5, _T6, _T7]]: ...
|
||||
|
||||
|
||||
@overload
|
||||
def select(
|
||||
__ent0: _TCCA[_T0],
|
||||
__ent1: _TCCA[_T1],
|
||||
__ent2: _TCCA[_T2],
|
||||
__ent3: _TCCA[_T3],
|
||||
__ent4: _TCCA[_T4],
|
||||
__ent5: _TCCA[_T5],
|
||||
__ent6: _TCCA[_T6],
|
||||
__ent7: _TCCA[_T7],
|
||||
__ent8: _TCCA[_T8],
|
||||
) -> Select[Tuple[_T0, _T1, _T2, _T3, _T4, _T5, _T6, _T7, _T8]]: ...
|
||||
|
||||
|
||||
@overload
|
||||
def select(
|
||||
__ent0: _TCCA[_T0],
|
||||
__ent1: _TCCA[_T1],
|
||||
__ent2: _TCCA[_T2],
|
||||
__ent3: _TCCA[_T3],
|
||||
__ent4: _TCCA[_T4],
|
||||
__ent5: _TCCA[_T5],
|
||||
__ent6: _TCCA[_T6],
|
||||
__ent7: _TCCA[_T7],
|
||||
__ent8: _TCCA[_T8],
|
||||
__ent9: _TCCA[_T9],
|
||||
) -> Select[Tuple[_T0, _T1, _T2, _T3, _T4, _T5, _T6, _T7, _T8, _T9]]: ...
|
||||
|
||||
|
||||
# END OVERLOADED FUNCTIONS select
|
||||
|
||||
|
||||
@overload
|
||||
def select(
|
||||
*entities: _ColumnsClauseArgument[Any], **__kw: Any
|
||||
) -> Select[Any]: ...
|
||||
|
||||
|
||||
def select(*entities: _ColumnsClauseArgument[Any], **__kw: Any) -> Select[Any]:
|
||||
r"""Construct a new :class:`_expression.Select`.
|
||||
|
||||
|
||||
.. versionadded:: 1.4 - The :func:`_sql.select` function now accepts
|
||||
column arguments positionally. The top-level :func:`_sql.select`
|
||||
function will automatically use the 1.x or 2.x style API based on
|
||||
the incoming arguments; using :func:`_sql.select` from the
|
||||
``sqlalchemy.future`` module will enforce that only the 2.x style
|
||||
constructor is used.
|
||||
|
||||
Similar functionality is also available via the
|
||||
:meth:`_expression.FromClause.select` method on any
|
||||
:class:`_expression.FromClause`.
|
||||
|
||||
.. seealso::
|
||||
|
||||
:ref:`tutorial_selecting_data` - in the :ref:`unified_tutorial`
|
||||
|
||||
:param \*entities:
|
||||
Entities to SELECT from. For Core usage, this is typically a series
|
||||
of :class:`_expression.ColumnElement` and / or
|
||||
:class:`_expression.FromClause`
|
||||
objects which will form the columns clause of the resulting
|
||||
statement. For those objects that are instances of
|
||||
:class:`_expression.FromClause` (typically :class:`_schema.Table`
|
||||
or :class:`_expression.Alias`
|
||||
objects), the :attr:`_expression.FromClause.c`
|
||||
collection is extracted
|
||||
to form a collection of :class:`_expression.ColumnElement` objects.
|
||||
|
||||
This parameter will also accept :class:`_expression.TextClause`
|
||||
constructs as
|
||||
given, as well as ORM-mapped classes.
|
||||
|
||||
"""
|
||||
# the keyword args are a necessary element in order for the typing
|
||||
# to work out w/ the varargs vs. having named "keyword" arguments that
|
||||
# aren't always present.
|
||||
if __kw:
|
||||
raise _no_kw()
|
||||
return Select(*entities)
|
||||
|
||||
|
||||
def table(name: str, *columns: ColumnClause[Any], **kw: Any) -> TableClause:
|
||||
"""Produce a new :class:`_expression.TableClause`.
|
||||
|
||||
The object returned is an instance of
|
||||
:class:`_expression.TableClause`, which
|
||||
represents the "syntactical" portion of the schema-level
|
||||
:class:`_schema.Table` object.
|
||||
It may be used to construct lightweight table constructs.
|
||||
|
||||
:param name: Name of the table.
|
||||
|
||||
:param columns: A collection of :func:`_expression.column` constructs.
|
||||
|
||||
:param schema: The schema name for this table.
|
||||
|
||||
.. versionadded:: 1.3.18 :func:`_expression.table` can now
|
||||
accept a ``schema`` argument.
|
||||
"""
|
||||
|
||||
return TableClause(name, *columns, **kw)
|
||||
|
||||
|
||||
def tablesample(
|
||||
selectable: _FromClauseArgument,
|
||||
sampling: Union[float, Function[Any]],
|
||||
name: Optional[str] = None,
|
||||
seed: Optional[roles.ExpressionElementRole[Any]] = None,
|
||||
) -> TableSample:
|
||||
"""Return a :class:`_expression.TableSample` object.
|
||||
|
||||
:class:`_expression.TableSample` is an :class:`_expression.Alias`
|
||||
subclass that represents
|
||||
a table with the TABLESAMPLE clause applied to it.
|
||||
:func:`_expression.tablesample`
|
||||
is also available from the :class:`_expression.FromClause`
|
||||
class via the
|
||||
:meth:`_expression.FromClause.tablesample` method.
|
||||
|
||||
The TABLESAMPLE clause allows selecting a randomly selected approximate
|
||||
percentage of rows from a table. It supports multiple sampling methods,
|
||||
most commonly BERNOULLI and SYSTEM.
|
||||
|
||||
e.g.::
|
||||
|
||||
from sqlalchemy import func
|
||||
|
||||
selectable = people.tablesample(
|
||||
func.bernoulli(1), name="alias", seed=func.random()
|
||||
)
|
||||
stmt = select(selectable.c.people_id)
|
||||
|
||||
Assuming ``people`` with a column ``people_id``, the above
|
||||
statement would render as:
|
||||
|
||||
.. sourcecode:: sql
|
||||
|
||||
SELECT alias.people_id FROM
|
||||
people AS alias TABLESAMPLE bernoulli(:bernoulli_1)
|
||||
REPEATABLE (random())
|
||||
|
||||
:param sampling: a ``float`` percentage between 0 and 100 or
|
||||
:class:`_functions.Function`.
|
||||
|
||||
:param name: optional alias name
|
||||
|
||||
:param seed: any real-valued SQL expression. When specified, the
|
||||
REPEATABLE sub-clause is also rendered.
|
||||
|
||||
"""
|
||||
return TableSample._factory(selectable, sampling, name=name, seed=seed)
|
||||
|
||||
|
||||
@overload
|
||||
def union(
|
||||
*selects: _TypedSelectable[_TP],
|
||||
) -> CompoundSelect[_TP]: ...
|
||||
|
||||
|
||||
@overload
|
||||
def union(
|
||||
*selects: _SelectStatementForCompoundArgument[_TP],
|
||||
) -> CompoundSelect[_TP]: ...
|
||||
|
||||
|
||||
def union(
|
||||
*selects: _SelectStatementForCompoundArgument[_TP],
|
||||
) -> CompoundSelect[_TP]:
|
||||
r"""Return a ``UNION`` of multiple selectables.
|
||||
|
||||
The returned object is an instance of
|
||||
:class:`_expression.CompoundSelect`.
|
||||
|
||||
A similar :func:`union()` method is available on all
|
||||
:class:`_expression.FromClause` subclasses.
|
||||
|
||||
:param \*selects:
|
||||
a list of :class:`_expression.Select` instances.
|
||||
|
||||
:param \**kwargs:
|
||||
available keyword arguments are the same as those of
|
||||
:func:`select`.
|
||||
|
||||
"""
|
||||
return CompoundSelect._create_union(*selects)
|
||||
|
||||
|
||||
@overload
|
||||
def union_all(
|
||||
*selects: _TypedSelectable[_TP],
|
||||
) -> CompoundSelect[_TP]: ...
|
||||
|
||||
|
||||
@overload
|
||||
def union_all(
|
||||
*selects: _SelectStatementForCompoundArgument[_TP],
|
||||
) -> CompoundSelect[_TP]: ...
|
||||
|
||||
|
||||
def union_all(
|
||||
*selects: _SelectStatementForCompoundArgument[_TP],
|
||||
) -> CompoundSelect[_TP]:
|
||||
r"""Return a ``UNION ALL`` of multiple selectables.
|
||||
|
||||
The returned object is an instance of
|
||||
:class:`_expression.CompoundSelect`.
|
||||
|
||||
A similar :func:`union_all()` method is available on all
|
||||
:class:`_expression.FromClause` subclasses.
|
||||
|
||||
:param \*selects:
|
||||
a list of :class:`_expression.Select` instances.
|
||||
|
||||
"""
|
||||
return CompoundSelect._create_union_all(*selects)
|
||||
|
||||
|
||||
def values(
|
||||
*columns: ColumnClause[Any],
|
||||
name: Optional[str] = None,
|
||||
literal_binds: bool = False,
|
||||
) -> Values:
|
||||
r"""Construct a :class:`_expression.Values` construct.
|
||||
|
||||
The column expressions and the actual data for
|
||||
:class:`_expression.Values` are given in two separate steps. The
|
||||
constructor receives the column expressions typically as
|
||||
:func:`_expression.column` constructs,
|
||||
and the data is then passed via the
|
||||
:meth:`_expression.Values.data` method as a list,
|
||||
which can be called multiple
|
||||
times to add more data, e.g.::
|
||||
|
||||
from sqlalchemy import column
|
||||
from sqlalchemy import values
|
||||
from sqlalchemy import Integer
|
||||
from sqlalchemy import String
|
||||
|
||||
value_expr = values(
|
||||
column("id", Integer),
|
||||
column("name", String),
|
||||
name="my_values",
|
||||
).data([(1, "name1"), (2, "name2"), (3, "name3")])
|
||||
|
||||
:param \*columns: column expressions, typically composed using
|
||||
:func:`_expression.column` objects.
|
||||
|
||||
:param name: the name for this VALUES construct. If omitted, the
|
||||
VALUES construct will be unnamed in a SQL expression. Different
|
||||
backends may have different requirements here.
|
||||
|
||||
:param literal_binds: Defaults to False. Whether or not to render
|
||||
the data values inline in the SQL output, rather than using bound
|
||||
parameters.
|
||||
|
||||
"""
|
||||
return Values(*columns, literal_binds=literal_binds, name=name)
|
463
venv/lib/python3.11/site-packages/sqlalchemy/sql/_typing.py
Normal file
463
venv/lib/python3.11/site-packages/sqlalchemy/sql/_typing.py
Normal file
@ -0,0 +1,463 @@
|
||||
# sql/_typing.py
|
||||
# Copyright (C) 2022-2025 the SQLAlchemy authors and contributors
|
||||
# <see AUTHORS file>
|
||||
#
|
||||
# This module is part of SQLAlchemy and is released under
|
||||
# the MIT License: https://www.opensource.org/licenses/mit-license.php
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import operator
|
||||
from typing import Any
|
||||
from typing import Callable
|
||||
from typing import Dict
|
||||
from typing import Generic
|
||||
from typing import Iterable
|
||||
from typing import Mapping
|
||||
from typing import NoReturn
|
||||
from typing import Optional
|
||||
from typing import overload
|
||||
from typing import Set
|
||||
from typing import Tuple
|
||||
from typing import Type
|
||||
from typing import TYPE_CHECKING
|
||||
from typing import TypeVar
|
||||
from typing import Union
|
||||
|
||||
from . import roles
|
||||
from .. import exc
|
||||
from .. import util
|
||||
from ..inspection import Inspectable
|
||||
from ..util.typing import Literal
|
||||
from ..util.typing import Protocol
|
||||
from ..util.typing import TypeAlias
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from datetime import date
|
||||
from datetime import datetime
|
||||
from datetime import time
|
||||
from datetime import timedelta
|
||||
from decimal import Decimal
|
||||
from uuid import UUID
|
||||
|
||||
from .base import Executable
|
||||
from .compiler import Compiled
|
||||
from .compiler import DDLCompiler
|
||||
from .compiler import SQLCompiler
|
||||
from .dml import UpdateBase
|
||||
from .dml import ValuesBase
|
||||
from .elements import ClauseElement
|
||||
from .elements import ColumnElement
|
||||
from .elements import KeyedColumnElement
|
||||
from .elements import quoted_name
|
||||
from .elements import SQLCoreOperations
|
||||
from .elements import TextClause
|
||||
from .lambdas import LambdaElement
|
||||
from .roles import FromClauseRole
|
||||
from .schema import Column
|
||||
from .selectable import Alias
|
||||
from .selectable import CompoundSelect
|
||||
from .selectable import CTE
|
||||
from .selectable import FromClause
|
||||
from .selectable import Join
|
||||
from .selectable import NamedFromClause
|
||||
from .selectable import ReturnsRows
|
||||
from .selectable import Select
|
||||
from .selectable import Selectable
|
||||
from .selectable import SelectBase
|
||||
from .selectable import Subquery
|
||||
from .selectable import TableClause
|
||||
from .sqltypes import TableValueType
|
||||
from .sqltypes import TupleType
|
||||
from .type_api import TypeEngine
|
||||
from ..engine import Dialect
|
||||
from ..util.typing import TypeGuard
|
||||
|
||||
_T = TypeVar("_T", bound=Any)
|
||||
_T_co = TypeVar("_T_co", bound=Any, covariant=True)
|
||||
|
||||
|
||||
_CE = TypeVar("_CE", bound="ColumnElement[Any]")
|
||||
|
||||
_CLE = TypeVar("_CLE", bound="ClauseElement")
|
||||
|
||||
|
||||
class _HasClauseElement(Protocol, Generic[_T_co]):
|
||||
"""indicates a class that has a __clause_element__() method"""
|
||||
|
||||
def __clause_element__(self) -> roles.ExpressionElementRole[_T_co]: ...
|
||||
|
||||
|
||||
class _CoreAdapterProto(Protocol):
|
||||
"""protocol for the ClauseAdapter/ColumnAdapter.traverse() method."""
|
||||
|
||||
def __call__(self, obj: _CE) -> _CE: ...
|
||||
|
||||
|
||||
class _HasDialect(Protocol):
|
||||
"""protocol for Engine/Connection-like objects that have dialect
|
||||
attribute.
|
||||
"""
|
||||
|
||||
@property
|
||||
def dialect(self) -> Dialect: ...
|
||||
|
||||
|
||||
# match column types that are not ORM entities
|
||||
_NOT_ENTITY = TypeVar(
|
||||
"_NOT_ENTITY",
|
||||
int,
|
||||
str,
|
||||
bool,
|
||||
"datetime",
|
||||
"date",
|
||||
"time",
|
||||
"timedelta",
|
||||
"UUID",
|
||||
float,
|
||||
"Decimal",
|
||||
)
|
||||
|
||||
_StarOrOne = Literal["*", 1]
|
||||
|
||||
_MAYBE_ENTITY = TypeVar(
|
||||
"_MAYBE_ENTITY",
|
||||
roles.ColumnsClauseRole,
|
||||
_StarOrOne,
|
||||
Type[Any],
|
||||
Inspectable[_HasClauseElement[Any]],
|
||||
_HasClauseElement[Any],
|
||||
)
|
||||
|
||||
|
||||
# convention:
|
||||
# XYZArgument - something that the end user is passing to a public API method
|
||||
# XYZElement - the internal representation that we use for the thing.
|
||||
# the coercions system is responsible for converting from XYZArgument to
|
||||
# XYZElement.
|
||||
|
||||
_TextCoercedExpressionArgument = Union[
|
||||
str,
|
||||
"TextClause",
|
||||
"ColumnElement[_T]",
|
||||
_HasClauseElement[_T],
|
||||
roles.ExpressionElementRole[_T],
|
||||
]
|
||||
|
||||
_ColumnsClauseArgument = Union[
|
||||
roles.TypedColumnsClauseRole[_T],
|
||||
roles.ColumnsClauseRole,
|
||||
"SQLCoreOperations[_T]",
|
||||
_StarOrOne,
|
||||
Type[_T],
|
||||
Inspectable[_HasClauseElement[_T]],
|
||||
_HasClauseElement[_T],
|
||||
]
|
||||
"""open-ended SELECT columns clause argument.
|
||||
|
||||
Includes column expressions, tables, ORM mapped entities, a few literal values.
|
||||
|
||||
This type is used for lists of columns / entities to be returned in result
|
||||
sets; select(...), insert().returning(...), etc.
|
||||
|
||||
|
||||
"""
|
||||
|
||||
_TypedColumnClauseArgument = Union[
|
||||
roles.TypedColumnsClauseRole[_T],
|
||||
"SQLCoreOperations[_T]",
|
||||
Type[_T],
|
||||
]
|
||||
|
||||
_TP = TypeVar("_TP", bound=Tuple[Any, ...])
|
||||
|
||||
_T0 = TypeVar("_T0", bound=Any)
|
||||
_T1 = TypeVar("_T1", bound=Any)
|
||||
_T2 = TypeVar("_T2", bound=Any)
|
||||
_T3 = TypeVar("_T3", bound=Any)
|
||||
_T4 = TypeVar("_T4", bound=Any)
|
||||
_T5 = TypeVar("_T5", bound=Any)
|
||||
_T6 = TypeVar("_T6", bound=Any)
|
||||
_T7 = TypeVar("_T7", bound=Any)
|
||||
_T8 = TypeVar("_T8", bound=Any)
|
||||
_T9 = TypeVar("_T9", bound=Any)
|
||||
|
||||
|
||||
_ColumnExpressionArgument = Union[
|
||||
"ColumnElement[_T]",
|
||||
_HasClauseElement[_T],
|
||||
"SQLCoreOperations[_T]",
|
||||
roles.ExpressionElementRole[_T],
|
||||
roles.TypedColumnsClauseRole[_T],
|
||||
Callable[[], "ColumnElement[_T]"],
|
||||
"LambdaElement",
|
||||
]
|
||||
"See docs in public alias ColumnExpressionArgument."
|
||||
|
||||
ColumnExpressionArgument: TypeAlias = _ColumnExpressionArgument[_T]
|
||||
"""Narrower "column expression" argument.
|
||||
|
||||
This type is used for all the other "column" kinds of expressions that
|
||||
typically represent a single SQL column expression, not a set of columns the
|
||||
way a table or ORM entity does.
|
||||
|
||||
This includes ColumnElement, or ORM-mapped attributes that will have a
|
||||
``__clause_element__()`` method, it also has the ExpressionElementRole
|
||||
overall which brings in the TextClause object also.
|
||||
|
||||
.. versionadded:: 2.0.13
|
||||
|
||||
"""
|
||||
|
||||
_ColumnExpressionOrLiteralArgument = Union[Any, _ColumnExpressionArgument[_T]]
|
||||
|
||||
_ColumnExpressionOrStrLabelArgument = Union[str, _ColumnExpressionArgument[_T]]
|
||||
|
||||
_ByArgument = Union[
|
||||
Iterable[_ColumnExpressionOrStrLabelArgument[Any]],
|
||||
_ColumnExpressionOrStrLabelArgument[Any],
|
||||
]
|
||||
"""Used for keyword-based ``order_by`` and ``partition_by`` parameters."""
|
||||
|
||||
|
||||
_InfoType = Dict[Any, Any]
|
||||
"""the .info dictionary accepted and used throughout Core /ORM"""
|
||||
|
||||
_FromClauseArgument = Union[
|
||||
roles.FromClauseRole,
|
||||
Type[Any],
|
||||
Inspectable[_HasClauseElement[Any]],
|
||||
_HasClauseElement[Any],
|
||||
]
|
||||
"""A FROM clause, like we would send to select().select_from().
|
||||
|
||||
Also accommodates ORM entities and related constructs.
|
||||
|
||||
"""
|
||||
|
||||
_JoinTargetArgument = Union[_FromClauseArgument, roles.JoinTargetRole]
|
||||
"""target for join() builds on _FromClauseArgument to include additional
|
||||
join target roles such as those which come from the ORM.
|
||||
|
||||
"""
|
||||
|
||||
_OnClauseArgument = Union[_ColumnExpressionArgument[Any], roles.OnClauseRole]
|
||||
"""target for an ON clause, includes additional roles such as those which
|
||||
come from the ORM.
|
||||
|
||||
"""
|
||||
|
||||
_SelectStatementForCompoundArgument = Union[
|
||||
"Select[_TP]",
|
||||
"CompoundSelect[_TP]",
|
||||
roles.CompoundElementRole,
|
||||
]
|
||||
"""SELECT statement acceptable by ``union()`` and other SQL set operations"""
|
||||
|
||||
_DMLColumnArgument = Union[
|
||||
str,
|
||||
_HasClauseElement[Any],
|
||||
roles.DMLColumnRole,
|
||||
"SQLCoreOperations[Any]",
|
||||
]
|
||||
"""A DML column expression. This is a "key" inside of insert().values(),
|
||||
update().values(), and related.
|
||||
|
||||
These are usually strings or SQL table columns.
|
||||
|
||||
There's also edge cases like JSON expression assignment, which we would want
|
||||
the DMLColumnRole to be able to accommodate.
|
||||
|
||||
"""
|
||||
|
||||
_DMLKey = TypeVar("_DMLKey", bound=_DMLColumnArgument)
|
||||
_DMLColumnKeyMapping = Mapping[_DMLKey, Any]
|
||||
|
||||
|
||||
_DDLColumnArgument = Union[str, "Column[Any]", roles.DDLConstraintColumnRole]
|
||||
"""DDL column.
|
||||
|
||||
used for :class:`.PrimaryKeyConstraint`, :class:`.UniqueConstraint`, etc.
|
||||
|
||||
"""
|
||||
|
||||
_DMLTableArgument = Union[
|
||||
"TableClause",
|
||||
"Join",
|
||||
"Alias",
|
||||
"CTE",
|
||||
Type[Any],
|
||||
Inspectable[_HasClauseElement[Any]],
|
||||
_HasClauseElement[Any],
|
||||
]
|
||||
|
||||
_PropagateAttrsType = util.immutabledict[str, Any]
|
||||
|
||||
_TypeEngineArgument = Union[Type["TypeEngine[_T]"], "TypeEngine[_T]"]
|
||||
|
||||
_EquivalentColumnMap = Dict["ColumnElement[Any]", Set["ColumnElement[Any]"]]
|
||||
|
||||
_LimitOffsetType = Union[int, _ColumnExpressionArgument[int], None]
|
||||
|
||||
_AutoIncrementType = Union[bool, Literal["auto", "ignore_fk"]]
|
||||
|
||||
if TYPE_CHECKING:
|
||||
|
||||
def is_sql_compiler(c: Compiled) -> TypeGuard[SQLCompiler]: ...
|
||||
|
||||
def is_ddl_compiler(c: Compiled) -> TypeGuard[DDLCompiler]: ...
|
||||
|
||||
def is_named_from_clause(
|
||||
t: FromClauseRole,
|
||||
) -> TypeGuard[NamedFromClause]: ...
|
||||
|
||||
def is_column_element(
|
||||
c: ClauseElement,
|
||||
) -> TypeGuard[ColumnElement[Any]]: ...
|
||||
|
||||
def is_keyed_column_element(
|
||||
c: ClauseElement,
|
||||
) -> TypeGuard[KeyedColumnElement[Any]]: ...
|
||||
|
||||
def is_text_clause(c: ClauseElement) -> TypeGuard[TextClause]: ...
|
||||
|
||||
def is_from_clause(c: ClauseElement) -> TypeGuard[FromClause]: ...
|
||||
|
||||
def is_tuple_type(t: TypeEngine[Any]) -> TypeGuard[TupleType]: ...
|
||||
|
||||
def is_table_value_type(
|
||||
t: TypeEngine[Any],
|
||||
) -> TypeGuard[TableValueType]: ...
|
||||
|
||||
def is_selectable(t: Any) -> TypeGuard[Selectable]: ...
|
||||
|
||||
def is_select_base(
|
||||
t: Union[Executable, ReturnsRows]
|
||||
) -> TypeGuard[SelectBase]: ...
|
||||
|
||||
def is_select_statement(
|
||||
t: Union[Executable, ReturnsRows]
|
||||
) -> TypeGuard[Select[Any]]: ...
|
||||
|
||||
def is_table(t: FromClause) -> TypeGuard[TableClause]: ...
|
||||
|
||||
def is_subquery(t: FromClause) -> TypeGuard[Subquery]: ...
|
||||
|
||||
def is_dml(c: ClauseElement) -> TypeGuard[UpdateBase]: ...
|
||||
|
||||
else:
|
||||
is_sql_compiler = operator.attrgetter("is_sql")
|
||||
is_ddl_compiler = operator.attrgetter("is_ddl")
|
||||
is_named_from_clause = operator.attrgetter("named_with_column")
|
||||
is_column_element = operator.attrgetter("_is_column_element")
|
||||
is_keyed_column_element = operator.attrgetter("_is_keyed_column_element")
|
||||
is_text_clause = operator.attrgetter("_is_text_clause")
|
||||
is_from_clause = operator.attrgetter("_is_from_clause")
|
||||
is_tuple_type = operator.attrgetter("_is_tuple_type")
|
||||
is_table_value_type = operator.attrgetter("_is_table_value")
|
||||
is_selectable = operator.attrgetter("is_selectable")
|
||||
is_select_base = operator.attrgetter("_is_select_base")
|
||||
is_select_statement = operator.attrgetter("_is_select_statement")
|
||||
is_table = operator.attrgetter("_is_table")
|
||||
is_subquery = operator.attrgetter("_is_subquery")
|
||||
is_dml = operator.attrgetter("is_dml")
|
||||
|
||||
|
||||
def has_schema_attr(t: FromClauseRole) -> TypeGuard[TableClause]:
|
||||
return hasattr(t, "schema")
|
||||
|
||||
|
||||
def is_quoted_name(s: str) -> TypeGuard[quoted_name]:
|
||||
return hasattr(s, "quote")
|
||||
|
||||
|
||||
def is_has_clause_element(s: object) -> TypeGuard[_HasClauseElement[Any]]:
|
||||
return hasattr(s, "__clause_element__")
|
||||
|
||||
|
||||
def is_insert_update(c: ClauseElement) -> TypeGuard[ValuesBase]:
|
||||
return c.is_dml and (c.is_insert or c.is_update) # type: ignore
|
||||
|
||||
|
||||
def _no_kw() -> exc.ArgumentError:
|
||||
return exc.ArgumentError(
|
||||
"Additional keyword arguments are not accepted by this "
|
||||
"function/method. The presence of **kw is for pep-484 typing purposes"
|
||||
)
|
||||
|
||||
|
||||
def _unexpected_kw(methname: str, kw: Dict[str, Any]) -> NoReturn:
|
||||
k = list(kw)[0]
|
||||
raise TypeError(f"{methname} got an unexpected keyword argument '{k}'")
|
||||
|
||||
|
||||
@overload
|
||||
def Nullable(
|
||||
val: "SQLCoreOperations[_T]",
|
||||
) -> "SQLCoreOperations[Optional[_T]]": ...
|
||||
|
||||
|
||||
@overload
|
||||
def Nullable(
|
||||
val: roles.ExpressionElementRole[_T],
|
||||
) -> roles.ExpressionElementRole[Optional[_T]]: ...
|
||||
|
||||
|
||||
@overload
|
||||
def Nullable(val: Type[_T]) -> Type[Optional[_T]]: ...
|
||||
|
||||
|
||||
def Nullable(
|
||||
val: _TypedColumnClauseArgument[_T],
|
||||
) -> _TypedColumnClauseArgument[Optional[_T]]:
|
||||
"""Types a column or ORM class as nullable.
|
||||
|
||||
This can be used in select and other contexts to express that the value of
|
||||
a column can be null, for example due to an outer join::
|
||||
|
||||
stmt1 = select(A, Nullable(B)).outerjoin(A.bs)
|
||||
stmt2 = select(A.data, Nullable(B.data)).outerjoin(A.bs)
|
||||
|
||||
At runtime this method returns the input unchanged.
|
||||
|
||||
.. versionadded:: 2.0.20
|
||||
"""
|
||||
return val
|
||||
|
||||
|
||||
@overload
|
||||
def NotNullable(
|
||||
val: "SQLCoreOperations[Optional[_T]]",
|
||||
) -> "SQLCoreOperations[_T]": ...
|
||||
|
||||
|
||||
@overload
|
||||
def NotNullable(
|
||||
val: roles.ExpressionElementRole[Optional[_T]],
|
||||
) -> roles.ExpressionElementRole[_T]: ...
|
||||
|
||||
|
||||
@overload
|
||||
def NotNullable(val: Type[Optional[_T]]) -> Type[_T]: ...
|
||||
|
||||
|
||||
@overload
|
||||
def NotNullable(val: Optional[Type[_T]]) -> Type[_T]: ...
|
||||
|
||||
|
||||
def NotNullable(
|
||||
val: Union[_TypedColumnClauseArgument[Optional[_T]], Optional[Type[_T]]],
|
||||
) -> _TypedColumnClauseArgument[_T]:
|
||||
"""Types a column or ORM class as not nullable.
|
||||
|
||||
This can be used in select and other contexts to express that the value of
|
||||
a column cannot be null, for example due to a where condition on a
|
||||
nullable column::
|
||||
|
||||
stmt = select(NotNullable(A.value)).where(A.value.is_not(None))
|
||||
|
||||
At runtime this method returns the input unchanged.
|
||||
|
||||
.. versionadded:: 2.0.20
|
||||
"""
|
||||
return val # type: ignore
|
585
venv/lib/python3.11/site-packages/sqlalchemy/sql/annotation.py
Normal file
585
venv/lib/python3.11/site-packages/sqlalchemy/sql/annotation.py
Normal file
@ -0,0 +1,585 @@
|
||||
# sql/annotation.py
|
||||
# Copyright (C) 2005-2025 the SQLAlchemy authors and contributors
|
||||
# <see AUTHORS file>
|
||||
#
|
||||
# This module is part of SQLAlchemy and is released under
|
||||
# the MIT License: https://www.opensource.org/licenses/mit-license.php
|
||||
|
||||
"""The :class:`.Annotated` class and related routines; creates hash-equivalent
|
||||
copies of SQL constructs which contain context-specific markers and
|
||||
associations.
|
||||
|
||||
Note that the :class:`.Annotated` concept as implemented in this module is not
|
||||
related in any way to the pep-593 concept of "Annotated".
|
||||
|
||||
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import typing
|
||||
from typing import Any
|
||||
from typing import Callable
|
||||
from typing import cast
|
||||
from typing import Dict
|
||||
from typing import FrozenSet
|
||||
from typing import Mapping
|
||||
from typing import Optional
|
||||
from typing import overload
|
||||
from typing import Sequence
|
||||
from typing import Tuple
|
||||
from typing import Type
|
||||
from typing import TYPE_CHECKING
|
||||
from typing import TypeVar
|
||||
|
||||
from . import operators
|
||||
from .cache_key import HasCacheKey
|
||||
from .visitors import anon_map
|
||||
from .visitors import ExternallyTraversible
|
||||
from .visitors import InternalTraversal
|
||||
from .. import util
|
||||
from ..util.typing import Literal
|
||||
from ..util.typing import Self
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from .base import _EntityNamespace
|
||||
from .visitors import _TraverseInternalsType
|
||||
|
||||
_AnnotationDict = Mapping[str, Any]
|
||||
|
||||
EMPTY_ANNOTATIONS: util.immutabledict[str, Any] = util.EMPTY_DICT
|
||||
|
||||
|
||||
class SupportsAnnotations(ExternallyTraversible):
|
||||
__slots__ = ()
|
||||
|
||||
_annotations: util.immutabledict[str, Any] = EMPTY_ANNOTATIONS
|
||||
|
||||
proxy_set: util.generic_fn_descriptor[FrozenSet[Any]]
|
||||
|
||||
_is_immutable: bool
|
||||
|
||||
def _annotate(self, values: _AnnotationDict) -> Self:
|
||||
raise NotImplementedError()
|
||||
|
||||
@overload
|
||||
def _deannotate(
|
||||
self,
|
||||
values: Literal[None] = ...,
|
||||
clone: bool = ...,
|
||||
) -> Self: ...
|
||||
|
||||
@overload
|
||||
def _deannotate(
|
||||
self,
|
||||
values: Sequence[str] = ...,
|
||||
clone: bool = ...,
|
||||
) -> SupportsAnnotations: ...
|
||||
|
||||
def _deannotate(
|
||||
self,
|
||||
values: Optional[Sequence[str]] = None,
|
||||
clone: bool = False,
|
||||
) -> SupportsAnnotations:
|
||||
raise NotImplementedError()
|
||||
|
||||
@util.memoized_property
|
||||
def _annotations_cache_key(self) -> Tuple[Any, ...]:
|
||||
anon_map_ = anon_map()
|
||||
|
||||
return self._gen_annotations_cache_key(anon_map_)
|
||||
|
||||
def _gen_annotations_cache_key(
|
||||
self, anon_map: anon_map
|
||||
) -> Tuple[Any, ...]:
|
||||
return (
|
||||
"_annotations",
|
||||
tuple(
|
||||
(
|
||||
key,
|
||||
(
|
||||
value._gen_cache_key(anon_map, [])
|
||||
if isinstance(value, HasCacheKey)
|
||||
else value
|
||||
),
|
||||
)
|
||||
for key, value in [
|
||||
(key, self._annotations[key])
|
||||
for key in sorted(self._annotations)
|
||||
]
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
class SupportsWrappingAnnotations(SupportsAnnotations):
|
||||
__slots__ = ()
|
||||
|
||||
_constructor: Callable[..., SupportsWrappingAnnotations]
|
||||
|
||||
if TYPE_CHECKING:
|
||||
|
||||
@util.ro_non_memoized_property
|
||||
def entity_namespace(self) -> _EntityNamespace: ...
|
||||
|
||||
def _annotate(self, values: _AnnotationDict) -> Self:
|
||||
"""return a copy of this ClauseElement with annotations
|
||||
updated by the given dictionary.
|
||||
|
||||
"""
|
||||
return Annotated._as_annotated_instance(self, values) # type: ignore
|
||||
|
||||
def _with_annotations(self, values: _AnnotationDict) -> Self:
|
||||
"""return a copy of this ClauseElement with annotations
|
||||
replaced by the given dictionary.
|
||||
|
||||
"""
|
||||
return Annotated._as_annotated_instance(self, values) # type: ignore
|
||||
|
||||
@overload
|
||||
def _deannotate(
|
||||
self,
|
||||
values: Literal[None] = ...,
|
||||
clone: bool = ...,
|
||||
) -> Self: ...
|
||||
|
||||
@overload
|
||||
def _deannotate(
|
||||
self,
|
||||
values: Sequence[str] = ...,
|
||||
clone: bool = ...,
|
||||
) -> SupportsAnnotations: ...
|
||||
|
||||
def _deannotate(
|
||||
self,
|
||||
values: Optional[Sequence[str]] = None,
|
||||
clone: bool = False,
|
||||
) -> SupportsAnnotations:
|
||||
"""return a copy of this :class:`_expression.ClauseElement`
|
||||
with annotations
|
||||
removed.
|
||||
|
||||
:param values: optional tuple of individual values
|
||||
to remove.
|
||||
|
||||
"""
|
||||
if clone:
|
||||
s = self._clone()
|
||||
return s
|
||||
else:
|
||||
return self
|
||||
|
||||
|
||||
class SupportsCloneAnnotations(SupportsWrappingAnnotations):
|
||||
# SupportsCloneAnnotations extends from SupportsWrappingAnnotations
|
||||
# to support the structure of having the base ClauseElement
|
||||
# be a subclass of SupportsWrappingAnnotations. Any ClauseElement
|
||||
# subclass that wants to extend from SupportsCloneAnnotations
|
||||
# will inherently also be subclassing SupportsWrappingAnnotations, so
|
||||
# make that specific here.
|
||||
|
||||
if not typing.TYPE_CHECKING:
|
||||
__slots__ = ()
|
||||
|
||||
_clone_annotations_traverse_internals: _TraverseInternalsType = [
|
||||
("_annotations", InternalTraversal.dp_annotations_key)
|
||||
]
|
||||
|
||||
def _annotate(self, values: _AnnotationDict) -> Self:
|
||||
"""return a copy of this ClauseElement with annotations
|
||||
updated by the given dictionary.
|
||||
|
||||
"""
|
||||
new = self._clone()
|
||||
new._annotations = new._annotations.union(values)
|
||||
new.__dict__.pop("_annotations_cache_key", None)
|
||||
new.__dict__.pop("_generate_cache_key", None)
|
||||
return new
|
||||
|
||||
def _with_annotations(self, values: _AnnotationDict) -> Self:
|
||||
"""return a copy of this ClauseElement with annotations
|
||||
replaced by the given dictionary.
|
||||
|
||||
"""
|
||||
new = self._clone()
|
||||
new._annotations = util.immutabledict(values)
|
||||
new.__dict__.pop("_annotations_cache_key", None)
|
||||
new.__dict__.pop("_generate_cache_key", None)
|
||||
return new
|
||||
|
||||
@overload
|
||||
def _deannotate(
|
||||
self,
|
||||
values: Literal[None] = ...,
|
||||
clone: bool = ...,
|
||||
) -> Self: ...
|
||||
|
||||
@overload
|
||||
def _deannotate(
|
||||
self,
|
||||
values: Sequence[str] = ...,
|
||||
clone: bool = ...,
|
||||
) -> SupportsAnnotations: ...
|
||||
|
||||
def _deannotate(
|
||||
self,
|
||||
values: Optional[Sequence[str]] = None,
|
||||
clone: bool = False,
|
||||
) -> SupportsAnnotations:
|
||||
"""return a copy of this :class:`_expression.ClauseElement`
|
||||
with annotations
|
||||
removed.
|
||||
|
||||
:param values: optional tuple of individual values
|
||||
to remove.
|
||||
|
||||
"""
|
||||
if clone or self._annotations:
|
||||
# clone is used when we are also copying
|
||||
# the expression for a deep deannotation
|
||||
new = self._clone()
|
||||
new._annotations = util.immutabledict()
|
||||
new.__dict__.pop("_annotations_cache_key", None)
|
||||
return new
|
||||
else:
|
||||
return self
|
||||
|
||||
|
||||
class Annotated(SupportsAnnotations):
|
||||
"""clones a SupportsAnnotations and applies an 'annotations' dictionary.
|
||||
|
||||
Unlike regular clones, this clone also mimics __hash__() and
|
||||
__eq__() of the original element so that it takes its place
|
||||
in hashed collections.
|
||||
|
||||
A reference to the original element is maintained, for the important
|
||||
reason of keeping its hash value current. When GC'ed, the
|
||||
hash value may be reused, causing conflicts.
|
||||
|
||||
.. note:: The rationale for Annotated producing a brand new class,
|
||||
rather than placing the functionality directly within ClauseElement,
|
||||
is **performance**. The __hash__() method is absent on plain
|
||||
ClauseElement which leads to significantly reduced function call
|
||||
overhead, as the use of sets and dictionaries against ClauseElement
|
||||
objects is prevalent, but most are not "annotated".
|
||||
|
||||
"""
|
||||
|
||||
_is_column_operators = False
|
||||
|
||||
@classmethod
|
||||
def _as_annotated_instance(
|
||||
cls, element: SupportsWrappingAnnotations, values: _AnnotationDict
|
||||
) -> Annotated:
|
||||
try:
|
||||
cls = annotated_classes[element.__class__]
|
||||
except KeyError:
|
||||
cls = _new_annotation_type(element.__class__, cls)
|
||||
return cls(element, values)
|
||||
|
||||
_annotations: util.immutabledict[str, Any]
|
||||
__element: SupportsWrappingAnnotations
|
||||
_hash: int
|
||||
|
||||
def __new__(cls: Type[Self], *args: Any) -> Self:
|
||||
return object.__new__(cls)
|
||||
|
||||
def __init__(
|
||||
self, element: SupportsWrappingAnnotations, values: _AnnotationDict
|
||||
):
|
||||
self.__dict__ = element.__dict__.copy()
|
||||
self.__dict__.pop("_annotations_cache_key", None)
|
||||
self.__dict__.pop("_generate_cache_key", None)
|
||||
self.__element = element
|
||||
self._annotations = util.immutabledict(values)
|
||||
self._hash = hash(element)
|
||||
|
||||
def _annotate(self, values: _AnnotationDict) -> Self:
|
||||
_values = self._annotations.union(values)
|
||||
new = self._with_annotations(_values)
|
||||
return new
|
||||
|
||||
def _with_annotations(self, values: _AnnotationDict) -> Self:
|
||||
clone = self.__class__.__new__(self.__class__)
|
||||
clone.__dict__ = self.__dict__.copy()
|
||||
clone.__dict__.pop("_annotations_cache_key", None)
|
||||
clone.__dict__.pop("_generate_cache_key", None)
|
||||
clone._annotations = util.immutabledict(values)
|
||||
return clone
|
||||
|
||||
@overload
|
||||
def _deannotate(
|
||||
self,
|
||||
values: Literal[None] = ...,
|
||||
clone: bool = ...,
|
||||
) -> Self: ...
|
||||
|
||||
@overload
|
||||
def _deannotate(
|
||||
self,
|
||||
values: Sequence[str] = ...,
|
||||
clone: bool = ...,
|
||||
) -> Annotated: ...
|
||||
|
||||
def _deannotate(
|
||||
self,
|
||||
values: Optional[Sequence[str]] = None,
|
||||
clone: bool = True,
|
||||
) -> SupportsAnnotations:
|
||||
if values is None:
|
||||
return self.__element
|
||||
else:
|
||||
return self._with_annotations(
|
||||
util.immutabledict(
|
||||
{
|
||||
key: value
|
||||
for key, value in self._annotations.items()
|
||||
if key not in values
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
if not typing.TYPE_CHECKING:
|
||||
# manually proxy some methods that need extra attention
|
||||
def _compiler_dispatch(self, visitor: Any, **kw: Any) -> Any:
|
||||
return self.__element.__class__._compiler_dispatch(
|
||||
self, visitor, **kw
|
||||
)
|
||||
|
||||
@property
|
||||
def _constructor(self):
|
||||
return self.__element._constructor
|
||||
|
||||
def _clone(self, **kw: Any) -> Self:
|
||||
clone = self.__element._clone(**kw)
|
||||
if clone is self.__element:
|
||||
# detect immutable, don't change anything
|
||||
return self
|
||||
else:
|
||||
# update the clone with any changes that have occurred
|
||||
# to this object's __dict__.
|
||||
clone.__dict__.update(self.__dict__)
|
||||
return self.__class__(clone, self._annotations)
|
||||
|
||||
def __reduce__(self) -> Tuple[Type[Annotated], Tuple[Any, ...]]:
|
||||
return self.__class__, (self.__element, self._annotations)
|
||||
|
||||
def __hash__(self) -> int:
|
||||
return self._hash
|
||||
|
||||
def __eq__(self, other: Any) -> bool:
|
||||
if self._is_column_operators:
|
||||
return self.__element.__class__.__eq__(self, other)
|
||||
else:
|
||||
return hash(other) == hash(self)
|
||||
|
||||
@util.ro_non_memoized_property
|
||||
def entity_namespace(self) -> _EntityNamespace:
|
||||
if "entity_namespace" in self._annotations:
|
||||
return cast(
|
||||
SupportsWrappingAnnotations,
|
||||
self._annotations["entity_namespace"],
|
||||
).entity_namespace
|
||||
else:
|
||||
return self.__element.entity_namespace
|
||||
|
||||
|
||||
# hard-generate Annotated subclasses. this technique
|
||||
# is used instead of on-the-fly types (i.e. type.__new__())
|
||||
# so that the resulting objects are pickleable; additionally, other
|
||||
# decisions can be made up front about the type of object being annotated
|
||||
# just once per class rather than per-instance.
|
||||
annotated_classes: Dict[Type[SupportsWrappingAnnotations], Type[Annotated]] = (
|
||||
{}
|
||||
)
|
||||
|
||||
_SA = TypeVar("_SA", bound="SupportsAnnotations")
|
||||
|
||||
|
||||
def _safe_annotate(to_annotate: _SA, annotations: _AnnotationDict) -> _SA:
|
||||
try:
|
||||
_annotate = to_annotate._annotate
|
||||
except AttributeError:
|
||||
# skip objects that don't actually have an `_annotate`
|
||||
# attribute, namely QueryableAttribute inside of a join
|
||||
# condition
|
||||
return to_annotate
|
||||
else:
|
||||
return _annotate(annotations)
|
||||
|
||||
|
||||
def _deep_annotate(
|
||||
element: _SA,
|
||||
annotations: _AnnotationDict,
|
||||
exclude: Optional[Sequence[SupportsAnnotations]] = None,
|
||||
*,
|
||||
detect_subquery_cols: bool = False,
|
||||
ind_cols_on_fromclause: bool = False,
|
||||
annotate_callable: Optional[
|
||||
Callable[[SupportsAnnotations, _AnnotationDict], SupportsAnnotations]
|
||||
] = None,
|
||||
) -> _SA:
|
||||
"""Deep copy the given ClauseElement, annotating each element
|
||||
with the given annotations dictionary.
|
||||
|
||||
Elements within the exclude collection will be cloned but not annotated.
|
||||
|
||||
"""
|
||||
|
||||
# annotated objects hack the __hash__() method so if we want to
|
||||
# uniquely process them we have to use id()
|
||||
|
||||
cloned_ids: Dict[int, SupportsAnnotations] = {}
|
||||
|
||||
def clone(elem: SupportsAnnotations, **kw: Any) -> SupportsAnnotations:
|
||||
# ind_cols_on_fromclause means make sure an AnnotatedFromClause
|
||||
# has its own .c collection independent of that which its proxying.
|
||||
# this is used specifically by orm.LoaderCriteriaOption to break
|
||||
# a reference cycle that it's otherwise prone to building,
|
||||
# see test_relationship_criteria->
|
||||
# test_loader_criteria_subquery_w_same_entity. logic here was
|
||||
# changed for #8796 and made explicit; previously it occurred
|
||||
# by accident
|
||||
|
||||
kw["detect_subquery_cols"] = detect_subquery_cols
|
||||
id_ = id(elem)
|
||||
|
||||
if id_ in cloned_ids:
|
||||
return cloned_ids[id_]
|
||||
|
||||
if (
|
||||
exclude
|
||||
and hasattr(elem, "proxy_set")
|
||||
and elem.proxy_set.intersection(exclude)
|
||||
):
|
||||
newelem = elem._clone(clone=clone, **kw)
|
||||
elif annotations != elem._annotations:
|
||||
if detect_subquery_cols and elem._is_immutable:
|
||||
to_annotate = elem._clone(clone=clone, **kw)
|
||||
else:
|
||||
to_annotate = elem
|
||||
if annotate_callable:
|
||||
newelem = annotate_callable(to_annotate, annotations)
|
||||
else:
|
||||
newelem = _safe_annotate(to_annotate, annotations)
|
||||
else:
|
||||
newelem = elem
|
||||
|
||||
newelem._copy_internals(
|
||||
clone=clone, ind_cols_on_fromclause=ind_cols_on_fromclause
|
||||
)
|
||||
|
||||
cloned_ids[id_] = newelem
|
||||
return newelem
|
||||
|
||||
if element is not None:
|
||||
element = cast(_SA, clone(element))
|
||||
clone = None # type: ignore # remove gc cycles
|
||||
return element
|
||||
|
||||
|
||||
@overload
|
||||
def _deep_deannotate(
|
||||
element: Literal[None], values: Optional[Sequence[str]] = None
|
||||
) -> Literal[None]: ...
|
||||
|
||||
|
||||
@overload
|
||||
def _deep_deannotate(
|
||||
element: _SA, values: Optional[Sequence[str]] = None
|
||||
) -> _SA: ...
|
||||
|
||||
|
||||
def _deep_deannotate(
|
||||
element: Optional[_SA], values: Optional[Sequence[str]] = None
|
||||
) -> Optional[_SA]:
|
||||
"""Deep copy the given element, removing annotations."""
|
||||
|
||||
cloned: Dict[Any, SupportsAnnotations] = {}
|
||||
|
||||
def clone(elem: SupportsAnnotations, **kw: Any) -> SupportsAnnotations:
|
||||
key: Any
|
||||
if values:
|
||||
key = id(elem)
|
||||
else:
|
||||
key = elem
|
||||
|
||||
if key not in cloned:
|
||||
newelem = elem._deannotate(values=values, clone=True)
|
||||
newelem._copy_internals(clone=clone)
|
||||
cloned[key] = newelem
|
||||
return newelem
|
||||
else:
|
||||
return cloned[key]
|
||||
|
||||
if element is not None:
|
||||
element = cast(_SA, clone(element))
|
||||
clone = None # type: ignore # remove gc cycles
|
||||
return element
|
||||
|
||||
|
||||
def _shallow_annotate(element: _SA, annotations: _AnnotationDict) -> _SA:
|
||||
"""Annotate the given ClauseElement and copy its internals so that
|
||||
internal objects refer to the new annotated object.
|
||||
|
||||
Basically used to apply a "don't traverse" annotation to a
|
||||
selectable, without digging throughout the whole
|
||||
structure wasting time.
|
||||
"""
|
||||
element = element._annotate(annotations)
|
||||
element._copy_internals()
|
||||
return element
|
||||
|
||||
|
||||
def _new_annotation_type(
|
||||
cls: Type[SupportsWrappingAnnotations], base_cls: Type[Annotated]
|
||||
) -> Type[Annotated]:
|
||||
"""Generates a new class that subclasses Annotated and proxies a given
|
||||
element type.
|
||||
|
||||
"""
|
||||
if issubclass(cls, Annotated):
|
||||
return cls
|
||||
elif cls in annotated_classes:
|
||||
return annotated_classes[cls]
|
||||
|
||||
for super_ in cls.__mro__:
|
||||
# check if an Annotated subclass more specific than
|
||||
# the given base_cls is already registered, such
|
||||
# as AnnotatedColumnElement.
|
||||
if super_ in annotated_classes:
|
||||
base_cls = annotated_classes[super_]
|
||||
break
|
||||
|
||||
annotated_classes[cls] = anno_cls = cast(
|
||||
Type[Annotated],
|
||||
type("Annotated%s" % cls.__name__, (base_cls, cls), {}),
|
||||
)
|
||||
globals()["Annotated%s" % cls.__name__] = anno_cls
|
||||
|
||||
if "_traverse_internals" in cls.__dict__:
|
||||
anno_cls._traverse_internals = list(cls._traverse_internals) + [
|
||||
("_annotations", InternalTraversal.dp_annotations_key)
|
||||
]
|
||||
elif cls.__dict__.get("inherit_cache", False):
|
||||
anno_cls._traverse_internals = list(cls._traverse_internals) + [
|
||||
("_annotations", InternalTraversal.dp_annotations_key)
|
||||
]
|
||||
|
||||
# some classes include this even if they have traverse_internals
|
||||
# e.g. BindParameter, add it if present.
|
||||
if cls.__dict__.get("inherit_cache", False):
|
||||
anno_cls.inherit_cache = True # type: ignore
|
||||
elif "inherit_cache" in cls.__dict__:
|
||||
anno_cls.inherit_cache = cls.__dict__["inherit_cache"] # type: ignore
|
||||
|
||||
anno_cls._is_column_operators = issubclass(cls, operators.ColumnOperators)
|
||||
|
||||
return anno_cls
|
||||
|
||||
|
||||
def _prepare_annotations(
|
||||
target_hierarchy: Type[SupportsWrappingAnnotations],
|
||||
base_cls: Type[Annotated],
|
||||
) -> None:
|
||||
for cls in util.walk_subclasses(target_hierarchy):
|
||||
_new_annotation_type(cls, base_cls)
|
2185
venv/lib/python3.11/site-packages/sqlalchemy/sql/base.py
Normal file
2185
venv/lib/python3.11/site-packages/sqlalchemy/sql/base.py
Normal file
File diff suppressed because it is too large
Load Diff
1057
venv/lib/python3.11/site-packages/sqlalchemy/sql/cache_key.py
Normal file
1057
venv/lib/python3.11/site-packages/sqlalchemy/sql/cache_key.py
Normal file
File diff suppressed because it is too large
Load Diff
1403
venv/lib/python3.11/site-packages/sqlalchemy/sql/coercions.py
Normal file
1403
venv/lib/python3.11/site-packages/sqlalchemy/sql/coercions.py
Normal file
File diff suppressed because it is too large
Load Diff
7946
venv/lib/python3.11/site-packages/sqlalchemy/sql/compiler.py
Normal file
7946
venv/lib/python3.11/site-packages/sqlalchemy/sql/compiler.py
Normal file
File diff suppressed because it is too large
Load Diff
1678
venv/lib/python3.11/site-packages/sqlalchemy/sql/crud.py
Normal file
1678
venv/lib/python3.11/site-packages/sqlalchemy/sql/crud.py
Normal file
File diff suppressed because it is too large
Load Diff
1441
venv/lib/python3.11/site-packages/sqlalchemy/sql/ddl.py
Normal file
1441
venv/lib/python3.11/site-packages/sqlalchemy/sql/ddl.py
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,552 @@
|
||||
# sql/default_comparator.py
|
||||
# Copyright (C) 2005-2025 the SQLAlchemy authors and contributors
|
||||
# <see AUTHORS file>
|
||||
#
|
||||
# This module is part of SQLAlchemy and is released under
|
||||
# the MIT License: https://www.opensource.org/licenses/mit-license.php
|
||||
|
||||
"""Default implementation of SQL comparison operations.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import typing
|
||||
from typing import Any
|
||||
from typing import Callable
|
||||
from typing import Dict
|
||||
from typing import NoReturn
|
||||
from typing import Optional
|
||||
from typing import Tuple
|
||||
from typing import Type
|
||||
from typing import Union
|
||||
|
||||
from . import coercions
|
||||
from . import operators
|
||||
from . import roles
|
||||
from . import type_api
|
||||
from .elements import and_
|
||||
from .elements import BinaryExpression
|
||||
from .elements import ClauseElement
|
||||
from .elements import CollationClause
|
||||
from .elements import CollectionAggregate
|
||||
from .elements import ExpressionClauseList
|
||||
from .elements import False_
|
||||
from .elements import Null
|
||||
from .elements import OperatorExpression
|
||||
from .elements import or_
|
||||
from .elements import True_
|
||||
from .elements import UnaryExpression
|
||||
from .operators import OperatorType
|
||||
from .. import exc
|
||||
from .. import util
|
||||
|
||||
_T = typing.TypeVar("_T", bound=Any)
|
||||
|
||||
if typing.TYPE_CHECKING:
|
||||
from .elements import ColumnElement
|
||||
from .operators import custom_op
|
||||
from .type_api import TypeEngine
|
||||
|
||||
|
||||
def _boolean_compare(
|
||||
expr: ColumnElement[Any],
|
||||
op: OperatorType,
|
||||
obj: Any,
|
||||
*,
|
||||
negate_op: Optional[OperatorType] = None,
|
||||
reverse: bool = False,
|
||||
_python_is_types: Tuple[Type[Any], ...] = (type(None), bool),
|
||||
result_type: Optional[TypeEngine[bool]] = None,
|
||||
**kwargs: Any,
|
||||
) -> OperatorExpression[bool]:
|
||||
if result_type is None:
|
||||
result_type = type_api.BOOLEANTYPE
|
||||
|
||||
if isinstance(obj, _python_is_types + (Null, True_, False_)):
|
||||
# allow x ==/!= True/False to be treated as a literal.
|
||||
# this comes out to "== / != true/false" or "1/0" if those
|
||||
# constants aren't supported and works on all platforms
|
||||
if op in (operators.eq, operators.ne) and isinstance(
|
||||
obj, (bool, True_, False_)
|
||||
):
|
||||
return OperatorExpression._construct_for_op(
|
||||
expr,
|
||||
coercions.expect(roles.ConstExprRole, obj),
|
||||
op,
|
||||
type_=result_type,
|
||||
negate=negate_op,
|
||||
modifiers=kwargs,
|
||||
)
|
||||
elif op in (
|
||||
operators.is_distinct_from,
|
||||
operators.is_not_distinct_from,
|
||||
):
|
||||
return OperatorExpression._construct_for_op(
|
||||
expr,
|
||||
coercions.expect(roles.ConstExprRole, obj),
|
||||
op,
|
||||
type_=result_type,
|
||||
negate=negate_op,
|
||||
modifiers=kwargs,
|
||||
)
|
||||
elif expr._is_collection_aggregate:
|
||||
obj = coercions.expect(
|
||||
roles.ConstExprRole, element=obj, operator=op, expr=expr
|
||||
)
|
||||
else:
|
||||
# all other None uses IS, IS NOT
|
||||
if op in (operators.eq, operators.is_):
|
||||
return OperatorExpression._construct_for_op(
|
||||
expr,
|
||||
coercions.expect(roles.ConstExprRole, obj),
|
||||
operators.is_,
|
||||
negate=operators.is_not,
|
||||
type_=result_type,
|
||||
)
|
||||
elif op in (operators.ne, operators.is_not):
|
||||
return OperatorExpression._construct_for_op(
|
||||
expr,
|
||||
coercions.expect(roles.ConstExprRole, obj),
|
||||
operators.is_not,
|
||||
negate=operators.is_,
|
||||
type_=result_type,
|
||||
)
|
||||
else:
|
||||
raise exc.ArgumentError(
|
||||
"Only '=', '!=', 'is_()', 'is_not()', "
|
||||
"'is_distinct_from()', 'is_not_distinct_from()' "
|
||||
"operators can be used with None/True/False"
|
||||
)
|
||||
else:
|
||||
obj = coercions.expect(
|
||||
roles.BinaryElementRole, element=obj, operator=op, expr=expr
|
||||
)
|
||||
|
||||
if reverse:
|
||||
return OperatorExpression._construct_for_op(
|
||||
obj,
|
||||
expr,
|
||||
op,
|
||||
type_=result_type,
|
||||
negate=negate_op,
|
||||
modifiers=kwargs,
|
||||
)
|
||||
else:
|
||||
return OperatorExpression._construct_for_op(
|
||||
expr,
|
||||
obj,
|
||||
op,
|
||||
type_=result_type,
|
||||
negate=negate_op,
|
||||
modifiers=kwargs,
|
||||
)
|
||||
|
||||
|
||||
def _custom_op_operate(
|
||||
expr: ColumnElement[Any],
|
||||
op: custom_op[Any],
|
||||
obj: Any,
|
||||
reverse: bool = False,
|
||||
result_type: Optional[TypeEngine[Any]] = None,
|
||||
**kw: Any,
|
||||
) -> ColumnElement[Any]:
|
||||
if result_type is None:
|
||||
if op.return_type:
|
||||
result_type = op.return_type
|
||||
elif op.is_comparison:
|
||||
result_type = type_api.BOOLEANTYPE
|
||||
|
||||
return _binary_operate(
|
||||
expr, op, obj, reverse=reverse, result_type=result_type, **kw
|
||||
)
|
||||
|
||||
|
||||
def _binary_operate(
|
||||
expr: ColumnElement[Any],
|
||||
op: OperatorType,
|
||||
obj: roles.BinaryElementRole[Any],
|
||||
*,
|
||||
reverse: bool = False,
|
||||
result_type: Optional[TypeEngine[_T]] = None,
|
||||
**kw: Any,
|
||||
) -> OperatorExpression[_T]:
|
||||
coerced_obj = coercions.expect(
|
||||
roles.BinaryElementRole, obj, expr=expr, operator=op
|
||||
)
|
||||
|
||||
if reverse:
|
||||
left, right = coerced_obj, expr
|
||||
else:
|
||||
left, right = expr, coerced_obj
|
||||
|
||||
if result_type is None:
|
||||
op, result_type = left.comparator._adapt_expression(
|
||||
op, right.comparator
|
||||
)
|
||||
|
||||
return OperatorExpression._construct_for_op(
|
||||
left, right, op, type_=result_type, modifiers=kw
|
||||
)
|
||||
|
||||
|
||||
def _conjunction_operate(
|
||||
expr: ColumnElement[Any], op: OperatorType, other: Any, **kw: Any
|
||||
) -> ColumnElement[Any]:
|
||||
if op is operators.and_:
|
||||
return and_(expr, other)
|
||||
elif op is operators.or_:
|
||||
return or_(expr, other)
|
||||
else:
|
||||
raise NotImplementedError()
|
||||
|
||||
|
||||
def _scalar(
|
||||
expr: ColumnElement[Any],
|
||||
op: OperatorType,
|
||||
fn: Callable[[ColumnElement[Any]], ColumnElement[Any]],
|
||||
**kw: Any,
|
||||
) -> ColumnElement[Any]:
|
||||
return fn(expr)
|
||||
|
||||
|
||||
def _in_impl(
|
||||
expr: ColumnElement[Any],
|
||||
op: OperatorType,
|
||||
seq_or_selectable: ClauseElement,
|
||||
negate_op: OperatorType,
|
||||
**kw: Any,
|
||||
) -> ColumnElement[Any]:
|
||||
seq_or_selectable = coercions.expect(
|
||||
roles.InElementRole, seq_or_selectable, expr=expr, operator=op
|
||||
)
|
||||
if "in_ops" in seq_or_selectable._annotations:
|
||||
op, negate_op = seq_or_selectable._annotations["in_ops"]
|
||||
|
||||
return _boolean_compare(
|
||||
expr, op, seq_or_selectable, negate_op=negate_op, **kw
|
||||
)
|
||||
|
||||
|
||||
def _getitem_impl(
|
||||
expr: ColumnElement[Any], op: OperatorType, other: Any, **kw: Any
|
||||
) -> ColumnElement[Any]:
|
||||
if (
|
||||
isinstance(expr.type, type_api.INDEXABLE)
|
||||
or isinstance(expr.type, type_api.TypeDecorator)
|
||||
and isinstance(expr.type.impl_instance, type_api.INDEXABLE)
|
||||
):
|
||||
other = coercions.expect(
|
||||
roles.BinaryElementRole, other, expr=expr, operator=op
|
||||
)
|
||||
return _binary_operate(expr, op, other, **kw)
|
||||
else:
|
||||
_unsupported_impl(expr, op, other, **kw)
|
||||
|
||||
|
||||
def _unsupported_impl(
|
||||
expr: ColumnElement[Any], op: OperatorType, *arg: Any, **kw: Any
|
||||
) -> NoReturn:
|
||||
raise NotImplementedError(
|
||||
"Operator '%s' is not supported on this expression" % op.__name__
|
||||
)
|
||||
|
||||
|
||||
def _inv_impl(
|
||||
expr: ColumnElement[Any], op: OperatorType, **kw: Any
|
||||
) -> ColumnElement[Any]:
|
||||
"""See :meth:`.ColumnOperators.__inv__`."""
|
||||
|
||||
# undocumented element currently used by the ORM for
|
||||
# relationship.contains()
|
||||
if hasattr(expr, "negation_clause"):
|
||||
return expr.negation_clause
|
||||
else:
|
||||
return expr._negate()
|
||||
|
||||
|
||||
def _neg_impl(
|
||||
expr: ColumnElement[Any], op: OperatorType, **kw: Any
|
||||
) -> ColumnElement[Any]:
|
||||
"""See :meth:`.ColumnOperators.__neg__`."""
|
||||
return UnaryExpression(expr, operator=operators.neg, type_=expr.type)
|
||||
|
||||
|
||||
def _bitwise_not_impl(
|
||||
expr: ColumnElement[Any], op: OperatorType, **kw: Any
|
||||
) -> ColumnElement[Any]:
|
||||
"""See :meth:`.ColumnOperators.bitwise_not`."""
|
||||
|
||||
return UnaryExpression(
|
||||
expr, operator=operators.bitwise_not_op, type_=expr.type
|
||||
)
|
||||
|
||||
|
||||
def _match_impl(
|
||||
expr: ColumnElement[Any], op: OperatorType, other: Any, **kw: Any
|
||||
) -> ColumnElement[Any]:
|
||||
"""See :meth:`.ColumnOperators.match`."""
|
||||
|
||||
return _boolean_compare(
|
||||
expr,
|
||||
operators.match_op,
|
||||
coercions.expect(
|
||||
roles.BinaryElementRole,
|
||||
other,
|
||||
expr=expr,
|
||||
operator=operators.match_op,
|
||||
),
|
||||
result_type=type_api.MATCHTYPE,
|
||||
negate_op=(
|
||||
operators.not_match_op
|
||||
if op is operators.match_op
|
||||
else operators.match_op
|
||||
),
|
||||
**kw,
|
||||
)
|
||||
|
||||
|
||||
def _distinct_impl(
|
||||
expr: ColumnElement[Any], op: OperatorType, **kw: Any
|
||||
) -> ColumnElement[Any]:
|
||||
"""See :meth:`.ColumnOperators.distinct`."""
|
||||
return UnaryExpression(
|
||||
expr, operator=operators.distinct_op, type_=expr.type
|
||||
)
|
||||
|
||||
|
||||
def _between_impl(
|
||||
expr: ColumnElement[Any],
|
||||
op: OperatorType,
|
||||
cleft: Any,
|
||||
cright: Any,
|
||||
**kw: Any,
|
||||
) -> ColumnElement[Any]:
|
||||
"""See :meth:`.ColumnOperators.between`."""
|
||||
return BinaryExpression(
|
||||
expr,
|
||||
ExpressionClauseList._construct_for_list(
|
||||
operators.and_,
|
||||
type_api.NULLTYPE,
|
||||
coercions.expect(
|
||||
roles.BinaryElementRole,
|
||||
cleft,
|
||||
expr=expr,
|
||||
operator=operators.and_,
|
||||
),
|
||||
coercions.expect(
|
||||
roles.BinaryElementRole,
|
||||
cright,
|
||||
expr=expr,
|
||||
operator=operators.and_,
|
||||
),
|
||||
group=False,
|
||||
),
|
||||
op,
|
||||
negate=(
|
||||
operators.not_between_op
|
||||
if op is operators.between_op
|
||||
else operators.between_op
|
||||
),
|
||||
modifiers=kw,
|
||||
)
|
||||
|
||||
|
||||
def _collate_impl(
|
||||
expr: ColumnElement[str], op: OperatorType, collation: str, **kw: Any
|
||||
) -> ColumnElement[str]:
|
||||
return CollationClause._create_collation_expression(expr, collation)
|
||||
|
||||
|
||||
def _regexp_match_impl(
|
||||
expr: ColumnElement[str],
|
||||
op: OperatorType,
|
||||
pattern: Any,
|
||||
flags: Optional[str],
|
||||
**kw: Any,
|
||||
) -> ColumnElement[Any]:
|
||||
return BinaryExpression(
|
||||
expr,
|
||||
coercions.expect(
|
||||
roles.BinaryElementRole,
|
||||
pattern,
|
||||
expr=expr,
|
||||
operator=operators.comma_op,
|
||||
),
|
||||
op,
|
||||
negate=operators.not_regexp_match_op,
|
||||
modifiers={"flags": flags},
|
||||
)
|
||||
|
||||
|
||||
def _regexp_replace_impl(
|
||||
expr: ColumnElement[Any],
|
||||
op: OperatorType,
|
||||
pattern: Any,
|
||||
replacement: Any,
|
||||
flags: Optional[str],
|
||||
**kw: Any,
|
||||
) -> ColumnElement[Any]:
|
||||
return BinaryExpression(
|
||||
expr,
|
||||
ExpressionClauseList._construct_for_list(
|
||||
operators.comma_op,
|
||||
type_api.NULLTYPE,
|
||||
coercions.expect(
|
||||
roles.BinaryElementRole,
|
||||
pattern,
|
||||
expr=expr,
|
||||
operator=operators.comma_op,
|
||||
),
|
||||
coercions.expect(
|
||||
roles.BinaryElementRole,
|
||||
replacement,
|
||||
expr=expr,
|
||||
operator=operators.comma_op,
|
||||
),
|
||||
group=False,
|
||||
),
|
||||
op,
|
||||
modifiers={"flags": flags},
|
||||
)
|
||||
|
||||
|
||||
# a mapping of operators with the method they use, along with
|
||||
# additional keyword arguments to be passed
|
||||
operator_lookup: Dict[
|
||||
str,
|
||||
Tuple[
|
||||
Callable[..., ColumnElement[Any]],
|
||||
util.immutabledict[
|
||||
str, Union[OperatorType, Callable[..., ColumnElement[Any]]]
|
||||
],
|
||||
],
|
||||
] = {
|
||||
"and_": (_conjunction_operate, util.EMPTY_DICT),
|
||||
"or_": (_conjunction_operate, util.EMPTY_DICT),
|
||||
"inv": (_inv_impl, util.EMPTY_DICT),
|
||||
"add": (_binary_operate, util.EMPTY_DICT),
|
||||
"mul": (_binary_operate, util.EMPTY_DICT),
|
||||
"sub": (_binary_operate, util.EMPTY_DICT),
|
||||
"div": (_binary_operate, util.EMPTY_DICT),
|
||||
"mod": (_binary_operate, util.EMPTY_DICT),
|
||||
"bitwise_xor_op": (_binary_operate, util.EMPTY_DICT),
|
||||
"bitwise_or_op": (_binary_operate, util.EMPTY_DICT),
|
||||
"bitwise_and_op": (_binary_operate, util.EMPTY_DICT),
|
||||
"bitwise_not_op": (_bitwise_not_impl, util.EMPTY_DICT),
|
||||
"bitwise_lshift_op": (_binary_operate, util.EMPTY_DICT),
|
||||
"bitwise_rshift_op": (_binary_operate, util.EMPTY_DICT),
|
||||
"truediv": (_binary_operate, util.EMPTY_DICT),
|
||||
"floordiv": (_binary_operate, util.EMPTY_DICT),
|
||||
"custom_op": (_custom_op_operate, util.EMPTY_DICT),
|
||||
"json_path_getitem_op": (_binary_operate, util.EMPTY_DICT),
|
||||
"json_getitem_op": (_binary_operate, util.EMPTY_DICT),
|
||||
"concat_op": (_binary_operate, util.EMPTY_DICT),
|
||||
"any_op": (
|
||||
_scalar,
|
||||
util.immutabledict({"fn": CollectionAggregate._create_any}),
|
||||
),
|
||||
"all_op": (
|
||||
_scalar,
|
||||
util.immutabledict({"fn": CollectionAggregate._create_all}),
|
||||
),
|
||||
"lt": (_boolean_compare, util.immutabledict({"negate_op": operators.ge})),
|
||||
"le": (_boolean_compare, util.immutabledict({"negate_op": operators.gt})),
|
||||
"ne": (_boolean_compare, util.immutabledict({"negate_op": operators.eq})),
|
||||
"gt": (_boolean_compare, util.immutabledict({"negate_op": operators.le})),
|
||||
"ge": (_boolean_compare, util.immutabledict({"negate_op": operators.lt})),
|
||||
"eq": (_boolean_compare, util.immutabledict({"negate_op": operators.ne})),
|
||||
"is_distinct_from": (
|
||||
_boolean_compare,
|
||||
util.immutabledict({"negate_op": operators.is_not_distinct_from}),
|
||||
),
|
||||
"is_not_distinct_from": (
|
||||
_boolean_compare,
|
||||
util.immutabledict({"negate_op": operators.is_distinct_from}),
|
||||
),
|
||||
"like_op": (
|
||||
_boolean_compare,
|
||||
util.immutabledict({"negate_op": operators.not_like_op}),
|
||||
),
|
||||
"ilike_op": (
|
||||
_boolean_compare,
|
||||
util.immutabledict({"negate_op": operators.not_ilike_op}),
|
||||
),
|
||||
"not_like_op": (
|
||||
_boolean_compare,
|
||||
util.immutabledict({"negate_op": operators.like_op}),
|
||||
),
|
||||
"not_ilike_op": (
|
||||
_boolean_compare,
|
||||
util.immutabledict({"negate_op": operators.ilike_op}),
|
||||
),
|
||||
"contains_op": (
|
||||
_boolean_compare,
|
||||
util.immutabledict({"negate_op": operators.not_contains_op}),
|
||||
),
|
||||
"icontains_op": (
|
||||
_boolean_compare,
|
||||
util.immutabledict({"negate_op": operators.not_icontains_op}),
|
||||
),
|
||||
"startswith_op": (
|
||||
_boolean_compare,
|
||||
util.immutabledict({"negate_op": operators.not_startswith_op}),
|
||||
),
|
||||
"istartswith_op": (
|
||||
_boolean_compare,
|
||||
util.immutabledict({"negate_op": operators.not_istartswith_op}),
|
||||
),
|
||||
"endswith_op": (
|
||||
_boolean_compare,
|
||||
util.immutabledict({"negate_op": operators.not_endswith_op}),
|
||||
),
|
||||
"iendswith_op": (
|
||||
_boolean_compare,
|
||||
util.immutabledict({"negate_op": operators.not_iendswith_op}),
|
||||
),
|
||||
"desc_op": (
|
||||
_scalar,
|
||||
util.immutabledict({"fn": UnaryExpression._create_desc}),
|
||||
),
|
||||
"asc_op": (
|
||||
_scalar,
|
||||
util.immutabledict({"fn": UnaryExpression._create_asc}),
|
||||
),
|
||||
"nulls_first_op": (
|
||||
_scalar,
|
||||
util.immutabledict({"fn": UnaryExpression._create_nulls_first}),
|
||||
),
|
||||
"nulls_last_op": (
|
||||
_scalar,
|
||||
util.immutabledict({"fn": UnaryExpression._create_nulls_last}),
|
||||
),
|
||||
"in_op": (
|
||||
_in_impl,
|
||||
util.immutabledict({"negate_op": operators.not_in_op}),
|
||||
),
|
||||
"not_in_op": (
|
||||
_in_impl,
|
||||
util.immutabledict({"negate_op": operators.in_op}),
|
||||
),
|
||||
"is_": (
|
||||
_boolean_compare,
|
||||
util.immutabledict({"negate_op": operators.is_}),
|
||||
),
|
||||
"is_not": (
|
||||
_boolean_compare,
|
||||
util.immutabledict({"negate_op": operators.is_not}),
|
||||
),
|
||||
"collate": (_collate_impl, util.EMPTY_DICT),
|
||||
"match_op": (_match_impl, util.EMPTY_DICT),
|
||||
"not_match_op": (_match_impl, util.EMPTY_DICT),
|
||||
"distinct_op": (_distinct_impl, util.EMPTY_DICT),
|
||||
"between_op": (_between_impl, util.EMPTY_DICT),
|
||||
"not_between_op": (_between_impl, util.EMPTY_DICT),
|
||||
"neg": (_neg_impl, util.EMPTY_DICT),
|
||||
"getitem": (_getitem_impl, util.EMPTY_DICT),
|
||||
"lshift": (_unsupported_impl, util.EMPTY_DICT),
|
||||
"rshift": (_unsupported_impl, util.EMPTY_DICT),
|
||||
"contains": (_unsupported_impl, util.EMPTY_DICT),
|
||||
"regexp_match_op": (_regexp_match_impl, util.EMPTY_DICT),
|
||||
"not_regexp_match_op": (_regexp_match_impl, util.EMPTY_DICT),
|
||||
"regexp_replace_op": (_regexp_replace_impl, util.EMPTY_DICT),
|
||||
}
|
1837
venv/lib/python3.11/site-packages/sqlalchemy/sql/dml.py
Normal file
1837
venv/lib/python3.11/site-packages/sqlalchemy/sql/dml.py
Normal file
File diff suppressed because it is too large
Load Diff
5544
venv/lib/python3.11/site-packages/sqlalchemy/sql/elements.py
Normal file
5544
venv/lib/python3.11/site-packages/sqlalchemy/sql/elements.py
Normal file
File diff suppressed because it is too large
Load Diff
458
venv/lib/python3.11/site-packages/sqlalchemy/sql/events.py
Normal file
458
venv/lib/python3.11/site-packages/sqlalchemy/sql/events.py
Normal file
@ -0,0 +1,458 @@
|
||||
# sql/events.py
|
||||
# Copyright (C) 2005-2025 the SQLAlchemy authors and contributors
|
||||
# <see AUTHORS file>
|
||||
#
|
||||
# This module is part of SQLAlchemy and is released under
|
||||
# the MIT License: https://www.opensource.org/licenses/mit-license.php
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from .base import SchemaEventTarget
|
||||
from .. import event
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from .schema import Column
|
||||
from .schema import Constraint
|
||||
from .schema import SchemaItem
|
||||
from .schema import Table
|
||||
from ..engine.base import Connection
|
||||
from ..engine.interfaces import ReflectedColumn
|
||||
from ..engine.reflection import Inspector
|
||||
|
||||
|
||||
class DDLEvents(event.Events[SchemaEventTarget]):
|
||||
"""
|
||||
Define event listeners for schema objects,
|
||||
that is, :class:`.SchemaItem` and other :class:`.SchemaEventTarget`
|
||||
subclasses, including :class:`_schema.MetaData`, :class:`_schema.Table`,
|
||||
:class:`_schema.Column`, etc.
|
||||
|
||||
**Create / Drop Events**
|
||||
|
||||
Events emitted when CREATE and DROP commands are emitted to the database.
|
||||
The event hooks in this category include :meth:`.DDLEvents.before_create`,
|
||||
:meth:`.DDLEvents.after_create`, :meth:`.DDLEvents.before_drop`, and
|
||||
:meth:`.DDLEvents.after_drop`.
|
||||
|
||||
These events are emitted when using schema-level methods such as
|
||||
:meth:`.MetaData.create_all` and :meth:`.MetaData.drop_all`. Per-object
|
||||
create/drop methods such as :meth:`.Table.create`, :meth:`.Table.drop`,
|
||||
:meth:`.Index.create` are also included, as well as dialect-specific
|
||||
methods such as :meth:`_postgresql.ENUM.create`.
|
||||
|
||||
.. versionadded:: 2.0 :class:`.DDLEvents` event hooks now take place
|
||||
for non-table objects including constraints, indexes, and
|
||||
dialect-specific schema types.
|
||||
|
||||
Event hooks may be attached directly to a :class:`_schema.Table` object or
|
||||
to a :class:`_schema.MetaData` collection, as well as to any
|
||||
:class:`.SchemaItem` class or object that can be individually created and
|
||||
dropped using a distinct SQL command. Such classes include :class:`.Index`,
|
||||
:class:`.Sequence`, and dialect-specific classes such as
|
||||
:class:`_postgresql.ENUM`.
|
||||
|
||||
Example using the :meth:`.DDLEvents.after_create` event, where a custom
|
||||
event hook will emit an ``ALTER TABLE`` command on the current connection,
|
||||
after ``CREATE TABLE`` is emitted::
|
||||
|
||||
from sqlalchemy import create_engine
|
||||
from sqlalchemy import event
|
||||
from sqlalchemy import Table, Column, Metadata, Integer
|
||||
|
||||
m = MetaData()
|
||||
some_table = Table("some_table", m, Column("data", Integer))
|
||||
|
||||
|
||||
@event.listens_for(some_table, "after_create")
|
||||
def after_create(target, connection, **kw):
|
||||
connection.execute(
|
||||
text("ALTER TABLE %s SET name=foo_%s" % (target.name, target.name))
|
||||
)
|
||||
|
||||
|
||||
some_engine = create_engine("postgresql://scott:tiger@host/test")
|
||||
|
||||
# will emit "CREATE TABLE some_table" as well as the above
|
||||
# "ALTER TABLE" statement afterwards
|
||||
m.create_all(some_engine)
|
||||
|
||||
Constraint objects such as :class:`.ForeignKeyConstraint`,
|
||||
:class:`.UniqueConstraint`, :class:`.CheckConstraint` may also be
|
||||
subscribed to these events, however they will **not** normally produce
|
||||
events as these objects are usually rendered inline within an
|
||||
enclosing ``CREATE TABLE`` statement and implicitly dropped from a
|
||||
``DROP TABLE`` statement.
|
||||
|
||||
For the :class:`.Index` construct, the event hook will be emitted
|
||||
for ``CREATE INDEX``, however SQLAlchemy does not normally emit
|
||||
``DROP INDEX`` when dropping tables as this is again implicit within the
|
||||
``DROP TABLE`` statement.
|
||||
|
||||
.. versionadded:: 2.0 Support for :class:`.SchemaItem` objects
|
||||
for create/drop events was expanded from its previous support for
|
||||
:class:`.MetaData` and :class:`.Table` to also include
|
||||
:class:`.Constraint` and all subclasses, :class:`.Index`,
|
||||
:class:`.Sequence` and some type-related constructs such as
|
||||
:class:`_postgresql.ENUM`.
|
||||
|
||||
.. note:: These event hooks are only emitted within the scope of
|
||||
SQLAlchemy's create/drop methods; they are not necessarily supported
|
||||
by tools such as `alembic <https://alembic.sqlalchemy.org>`_.
|
||||
|
||||
|
||||
**Attachment Events**
|
||||
|
||||
Attachment events are provided to customize
|
||||
behavior whenever a child schema element is associated
|
||||
with a parent, such as when a :class:`_schema.Column` is associated
|
||||
with its :class:`_schema.Table`, when a
|
||||
:class:`_schema.ForeignKeyConstraint`
|
||||
is associated with a :class:`_schema.Table`, etc. These events include
|
||||
:meth:`.DDLEvents.before_parent_attach` and
|
||||
:meth:`.DDLEvents.after_parent_attach`.
|
||||
|
||||
**Reflection Events**
|
||||
|
||||
The :meth:`.DDLEvents.column_reflect` event is used to intercept
|
||||
and modify the in-Python definition of database columns when
|
||||
:term:`reflection` of database tables proceeds.
|
||||
|
||||
**Use with Generic DDL**
|
||||
|
||||
DDL events integrate closely with the
|
||||
:class:`.DDL` class and the :class:`.ExecutableDDLElement` hierarchy
|
||||
of DDL clause constructs, which are themselves appropriate
|
||||
as listener callables::
|
||||
|
||||
from sqlalchemy import DDL
|
||||
|
||||
event.listen(
|
||||
some_table,
|
||||
"after_create",
|
||||
DDL("ALTER TABLE %(table)s SET name=foo_%(table)s"),
|
||||
)
|
||||
|
||||
**Event Propagation to MetaData Copies**
|
||||
|
||||
For all :class:`.DDLEvent` events, the ``propagate=True`` keyword argument
|
||||
will ensure that a given event handler is propagated to copies of the
|
||||
object, which are made when using the :meth:`_schema.Table.to_metadata`
|
||||
method::
|
||||
|
||||
from sqlalchemy import DDL
|
||||
|
||||
metadata = MetaData()
|
||||
some_table = Table("some_table", metadata, Column("data", Integer))
|
||||
|
||||
event.listen(
|
||||
some_table,
|
||||
"after_create",
|
||||
DDL("ALTER TABLE %(table)s SET name=foo_%(table)s"),
|
||||
propagate=True,
|
||||
)
|
||||
|
||||
new_metadata = MetaData()
|
||||
new_table = some_table.to_metadata(new_metadata)
|
||||
|
||||
The above :class:`.DDL` object will be associated with the
|
||||
:meth:`.DDLEvents.after_create` event for both the ``some_table`` and
|
||||
the ``new_table`` :class:`.Table` objects.
|
||||
|
||||
.. seealso::
|
||||
|
||||
:ref:`event_toplevel`
|
||||
|
||||
:class:`.ExecutableDDLElement`
|
||||
|
||||
:class:`.DDL`
|
||||
|
||||
:ref:`schema_ddl_sequences`
|
||||
|
||||
""" # noqa: E501
|
||||
|
||||
_target_class_doc = "SomeSchemaClassOrObject"
|
||||
_dispatch_target = SchemaEventTarget
|
||||
|
||||
def before_create(
|
||||
self, target: SchemaEventTarget, connection: Connection, **kw: Any
|
||||
) -> None:
|
||||
r"""Called before CREATE statements are emitted.
|
||||
|
||||
:param target: the :class:`.SchemaObject`, such as a
|
||||
:class:`_schema.MetaData` or :class:`_schema.Table`
|
||||
but also including all create/drop objects such as
|
||||
:class:`.Index`, :class:`.Sequence`, etc.,
|
||||
object which is the target of the event.
|
||||
|
||||
.. versionadded:: 2.0 Support for all :class:`.SchemaItem` objects
|
||||
was added.
|
||||
|
||||
:param connection: the :class:`_engine.Connection` where the
|
||||
CREATE statement or statements will be emitted.
|
||||
:param \**kw: additional keyword arguments relevant
|
||||
to the event. The contents of this dictionary
|
||||
may vary across releases, and include the
|
||||
list of tables being generated for a metadata-level
|
||||
event, the checkfirst flag, and other
|
||||
elements used by internal events.
|
||||
|
||||
:func:`.event.listen` accepts the ``propagate=True``
|
||||
modifier for this event; when True, the listener function will
|
||||
be established for any copies made of the target object,
|
||||
i.e. those copies that are generated when
|
||||
:meth:`_schema.Table.to_metadata` is used.
|
||||
|
||||
:func:`.event.listen` accepts the ``insert=True``
|
||||
modifier for this event; when True, the listener function will
|
||||
be prepended to the internal list of events upon discovery, and execute
|
||||
before registered listener functions that do not pass this argument.
|
||||
|
||||
"""
|
||||
|
||||
def after_create(
|
||||
self, target: SchemaEventTarget, connection: Connection, **kw: Any
|
||||
) -> None:
|
||||
r"""Called after CREATE statements are emitted.
|
||||
|
||||
:param target: the :class:`.SchemaObject`, such as a
|
||||
:class:`_schema.MetaData` or :class:`_schema.Table`
|
||||
but also including all create/drop objects such as
|
||||
:class:`.Index`, :class:`.Sequence`, etc.,
|
||||
object which is the target of the event.
|
||||
|
||||
.. versionadded:: 2.0 Support for all :class:`.SchemaItem` objects
|
||||
was added.
|
||||
|
||||
:param connection: the :class:`_engine.Connection` where the
|
||||
CREATE statement or statements have been emitted.
|
||||
:param \**kw: additional keyword arguments relevant
|
||||
to the event. The contents of this dictionary
|
||||
may vary across releases, and include the
|
||||
list of tables being generated for a metadata-level
|
||||
event, the checkfirst flag, and other
|
||||
elements used by internal events.
|
||||
|
||||
:func:`.event.listen` also accepts the ``propagate=True``
|
||||
modifier for this event; when True, the listener function will
|
||||
be established for any copies made of the target object,
|
||||
i.e. those copies that are generated when
|
||||
:meth:`_schema.Table.to_metadata` is used.
|
||||
|
||||
"""
|
||||
|
||||
def before_drop(
|
||||
self, target: SchemaEventTarget, connection: Connection, **kw: Any
|
||||
) -> None:
|
||||
r"""Called before DROP statements are emitted.
|
||||
|
||||
:param target: the :class:`.SchemaObject`, such as a
|
||||
:class:`_schema.MetaData` or :class:`_schema.Table`
|
||||
but also including all create/drop objects such as
|
||||
:class:`.Index`, :class:`.Sequence`, etc.,
|
||||
object which is the target of the event.
|
||||
|
||||
.. versionadded:: 2.0 Support for all :class:`.SchemaItem` objects
|
||||
was added.
|
||||
|
||||
:param connection: the :class:`_engine.Connection` where the
|
||||
DROP statement or statements will be emitted.
|
||||
:param \**kw: additional keyword arguments relevant
|
||||
to the event. The contents of this dictionary
|
||||
may vary across releases, and include the
|
||||
list of tables being generated for a metadata-level
|
||||
event, the checkfirst flag, and other
|
||||
elements used by internal events.
|
||||
|
||||
:func:`.event.listen` also accepts the ``propagate=True``
|
||||
modifier for this event; when True, the listener function will
|
||||
be established for any copies made of the target object,
|
||||
i.e. those copies that are generated when
|
||||
:meth:`_schema.Table.to_metadata` is used.
|
||||
|
||||
"""
|
||||
|
||||
def after_drop(
|
||||
self, target: SchemaEventTarget, connection: Connection, **kw: Any
|
||||
) -> None:
|
||||
r"""Called after DROP statements are emitted.
|
||||
|
||||
:param target: the :class:`.SchemaObject`, such as a
|
||||
:class:`_schema.MetaData` or :class:`_schema.Table`
|
||||
but also including all create/drop objects such as
|
||||
:class:`.Index`, :class:`.Sequence`, etc.,
|
||||
object which is the target of the event.
|
||||
|
||||
.. versionadded:: 2.0 Support for all :class:`.SchemaItem` objects
|
||||
was added.
|
||||
|
||||
:param connection: the :class:`_engine.Connection` where the
|
||||
DROP statement or statements have been emitted.
|
||||
:param \**kw: additional keyword arguments relevant
|
||||
to the event. The contents of this dictionary
|
||||
may vary across releases, and include the
|
||||
list of tables being generated for a metadata-level
|
||||
event, the checkfirst flag, and other
|
||||
elements used by internal events.
|
||||
|
||||
:func:`.event.listen` also accepts the ``propagate=True``
|
||||
modifier for this event; when True, the listener function will
|
||||
be established for any copies made of the target object,
|
||||
i.e. those copies that are generated when
|
||||
:meth:`_schema.Table.to_metadata` is used.
|
||||
|
||||
"""
|
||||
|
||||
def before_parent_attach(
|
||||
self, target: SchemaEventTarget, parent: SchemaItem
|
||||
) -> None:
|
||||
"""Called before a :class:`.SchemaItem` is associated with
|
||||
a parent :class:`.SchemaItem`.
|
||||
|
||||
:param target: the target object
|
||||
:param parent: the parent to which the target is being attached.
|
||||
|
||||
:func:`.event.listen` also accepts the ``propagate=True``
|
||||
modifier for this event; when True, the listener function will
|
||||
be established for any copies made of the target object,
|
||||
i.e. those copies that are generated when
|
||||
:meth:`_schema.Table.to_metadata` is used.
|
||||
|
||||
"""
|
||||
|
||||
def after_parent_attach(
|
||||
self, target: SchemaEventTarget, parent: SchemaItem
|
||||
) -> None:
|
||||
"""Called after a :class:`.SchemaItem` is associated with
|
||||
a parent :class:`.SchemaItem`.
|
||||
|
||||
:param target: the target object
|
||||
:param parent: the parent to which the target is being attached.
|
||||
|
||||
:func:`.event.listen` also accepts the ``propagate=True``
|
||||
modifier for this event; when True, the listener function will
|
||||
be established for any copies made of the target object,
|
||||
i.e. those copies that are generated when
|
||||
:meth:`_schema.Table.to_metadata` is used.
|
||||
|
||||
"""
|
||||
|
||||
def _sa_event_column_added_to_pk_constraint(
|
||||
self, const: Constraint, col: Column[Any]
|
||||
) -> None:
|
||||
"""internal event hook used for primary key naming convention
|
||||
updates.
|
||||
|
||||
"""
|
||||
|
||||
def column_reflect(
|
||||
self, inspector: Inspector, table: Table, column_info: ReflectedColumn
|
||||
) -> None:
|
||||
"""Called for each unit of 'column info' retrieved when
|
||||
a :class:`_schema.Table` is being reflected.
|
||||
|
||||
This event is most easily used by applying it to a specific
|
||||
:class:`_schema.MetaData` instance, where it will take effect for
|
||||
all :class:`_schema.Table` objects within that
|
||||
:class:`_schema.MetaData` that undergo reflection::
|
||||
|
||||
metadata = MetaData()
|
||||
|
||||
|
||||
@event.listens_for(metadata, "column_reflect")
|
||||
def receive_column_reflect(inspector, table, column_info):
|
||||
# receives for all Table objects that are reflected
|
||||
# under this MetaData
|
||||
...
|
||||
|
||||
|
||||
# will use the above event hook
|
||||
my_table = Table("my_table", metadata, autoload_with=some_engine)
|
||||
|
||||
.. versionadded:: 1.4.0b2 The :meth:`_events.DDLEvents.column_reflect`
|
||||
hook may now be applied to a :class:`_schema.MetaData` object as
|
||||
well as the :class:`_schema.MetaData` class itself where it will
|
||||
take place for all :class:`_schema.Table` objects associated with
|
||||
the targeted :class:`_schema.MetaData`.
|
||||
|
||||
It may also be applied to the :class:`_schema.Table` class across
|
||||
the board::
|
||||
|
||||
from sqlalchemy import Table
|
||||
|
||||
|
||||
@event.listens_for(Table, "column_reflect")
|
||||
def receive_column_reflect(inspector, table, column_info):
|
||||
# receives for all Table objects that are reflected
|
||||
...
|
||||
|
||||
It can also be applied to a specific :class:`_schema.Table` at the
|
||||
point that one is being reflected using the
|
||||
:paramref:`_schema.Table.listeners` parameter::
|
||||
|
||||
t1 = Table(
|
||||
"my_table",
|
||||
autoload_with=some_engine,
|
||||
listeners=[("column_reflect", receive_column_reflect)],
|
||||
)
|
||||
|
||||
The dictionary of column information as returned by the
|
||||
dialect is passed, and can be modified. The dictionary
|
||||
is that returned in each element of the list returned
|
||||
by :meth:`.reflection.Inspector.get_columns`:
|
||||
|
||||
* ``name`` - the column's name, is applied to the
|
||||
:paramref:`_schema.Column.name` parameter
|
||||
|
||||
* ``type`` - the type of this column, which should be an instance
|
||||
of :class:`~sqlalchemy.types.TypeEngine`, is applied to the
|
||||
:paramref:`_schema.Column.type` parameter
|
||||
|
||||
* ``nullable`` - boolean flag if the column is NULL or NOT NULL,
|
||||
is applied to the :paramref:`_schema.Column.nullable` parameter
|
||||
|
||||
* ``default`` - the column's server default value. This is
|
||||
normally specified as a plain string SQL expression, however the
|
||||
event can pass a :class:`.FetchedValue`, :class:`.DefaultClause`,
|
||||
or :func:`_expression.text` object as well. Is applied to the
|
||||
:paramref:`_schema.Column.server_default` parameter
|
||||
|
||||
The event is called before any action is taken against
|
||||
this dictionary, and the contents can be modified; the following
|
||||
additional keys may be added to the dictionary to further modify
|
||||
how the :class:`_schema.Column` is constructed:
|
||||
|
||||
|
||||
* ``key`` - the string key that will be used to access this
|
||||
:class:`_schema.Column` in the ``.c`` collection; will be applied
|
||||
to the :paramref:`_schema.Column.key` parameter. Is also used
|
||||
for ORM mapping. See the section
|
||||
:ref:`mapper_automated_reflection_schemes` for an example.
|
||||
|
||||
* ``quote`` - force or un-force quoting on the column name;
|
||||
is applied to the :paramref:`_schema.Column.quote` parameter.
|
||||
|
||||
* ``info`` - a dictionary of arbitrary data to follow along with
|
||||
the :class:`_schema.Column`, is applied to the
|
||||
:paramref:`_schema.Column.info` parameter.
|
||||
|
||||
:func:`.event.listen` also accepts the ``propagate=True``
|
||||
modifier for this event; when True, the listener function will
|
||||
be established for any copies made of the target object,
|
||||
i.e. those copies that are generated when
|
||||
:meth:`_schema.Table.to_metadata` is used.
|
||||
|
||||
.. seealso::
|
||||
|
||||
:ref:`mapper_automated_reflection_schemes` -
|
||||
in the ORM mapping documentation
|
||||
|
||||
:ref:`automap_intercepting_columns` -
|
||||
in the :ref:`automap_toplevel` documentation
|
||||
|
||||
:ref:`metadata_reflection_dbagnostic_types` - in
|
||||
the :ref:`metadata_reflection_toplevel` documentation
|
||||
|
||||
"""
|
162
venv/lib/python3.11/site-packages/sqlalchemy/sql/expression.py
Normal file
162
venv/lib/python3.11/site-packages/sqlalchemy/sql/expression.py
Normal file
@ -0,0 +1,162 @@
|
||||
# sql/expression.py
|
||||
# Copyright (C) 2005-2025 the SQLAlchemy authors and contributors
|
||||
# <see AUTHORS file>
|
||||
#
|
||||
# This module is part of SQLAlchemy and is released under
|
||||
# the MIT License: https://www.opensource.org/licenses/mit-license.php
|
||||
|
||||
"""Defines the public namespace for SQL expression constructs.
|
||||
|
||||
|
||||
"""
|
||||
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from ._dml_constructors import delete as delete
|
||||
from ._dml_constructors import insert as insert
|
||||
from ._dml_constructors import update as update
|
||||
from ._elements_constructors import all_ as all_
|
||||
from ._elements_constructors import and_ as and_
|
||||
from ._elements_constructors import any_ as any_
|
||||
from ._elements_constructors import asc as asc
|
||||
from ._elements_constructors import between as between
|
||||
from ._elements_constructors import bindparam as bindparam
|
||||
from ._elements_constructors import bitwise_not as bitwise_not
|
||||
from ._elements_constructors import case as case
|
||||
from ._elements_constructors import cast as cast
|
||||
from ._elements_constructors import collate as collate
|
||||
from ._elements_constructors import column as column
|
||||
from ._elements_constructors import desc as desc
|
||||
from ._elements_constructors import distinct as distinct
|
||||
from ._elements_constructors import extract as extract
|
||||
from ._elements_constructors import false as false
|
||||
from ._elements_constructors import funcfilter as funcfilter
|
||||
from ._elements_constructors import label as label
|
||||
from ._elements_constructors import not_ as not_
|
||||
from ._elements_constructors import null as null
|
||||
from ._elements_constructors import nulls_first as nulls_first
|
||||
from ._elements_constructors import nulls_last as nulls_last
|
||||
from ._elements_constructors import or_ as or_
|
||||
from ._elements_constructors import outparam as outparam
|
||||
from ._elements_constructors import over as over
|
||||
from ._elements_constructors import text as text
|
||||
from ._elements_constructors import true as true
|
||||
from ._elements_constructors import try_cast as try_cast
|
||||
from ._elements_constructors import tuple_ as tuple_
|
||||
from ._elements_constructors import type_coerce as type_coerce
|
||||
from ._elements_constructors import within_group as within_group
|
||||
from ._selectable_constructors import alias as alias
|
||||
from ._selectable_constructors import cte as cte
|
||||
from ._selectable_constructors import except_ as except_
|
||||
from ._selectable_constructors import except_all as except_all
|
||||
from ._selectable_constructors import exists as exists
|
||||
from ._selectable_constructors import intersect as intersect
|
||||
from ._selectable_constructors import intersect_all as intersect_all
|
||||
from ._selectable_constructors import join as join
|
||||
from ._selectable_constructors import lateral as lateral
|
||||
from ._selectable_constructors import outerjoin as outerjoin
|
||||
from ._selectable_constructors import select as select
|
||||
from ._selectable_constructors import table as table
|
||||
from ._selectable_constructors import tablesample as tablesample
|
||||
from ._selectable_constructors import union as union
|
||||
from ._selectable_constructors import union_all as union_all
|
||||
from ._selectable_constructors import values as values
|
||||
from ._typing import ColumnExpressionArgument as ColumnExpressionArgument
|
||||
from .base import _from_objects as _from_objects
|
||||
from .base import _select_iterables as _select_iterables
|
||||
from .base import ColumnCollection as ColumnCollection
|
||||
from .base import Executable as Executable
|
||||
from .cache_key import CacheKey as CacheKey
|
||||
from .dml import Delete as Delete
|
||||
from .dml import Insert as Insert
|
||||
from .dml import Update as Update
|
||||
from .dml import UpdateBase as UpdateBase
|
||||
from .dml import ValuesBase as ValuesBase
|
||||
from .elements import _truncated_label as _truncated_label
|
||||
from .elements import BinaryExpression as BinaryExpression
|
||||
from .elements import BindParameter as BindParameter
|
||||
from .elements import BooleanClauseList as BooleanClauseList
|
||||
from .elements import Case as Case
|
||||
from .elements import Cast as Cast
|
||||
from .elements import ClauseElement as ClauseElement
|
||||
from .elements import ClauseList as ClauseList
|
||||
from .elements import CollectionAggregate as CollectionAggregate
|
||||
from .elements import ColumnClause as ColumnClause
|
||||
from .elements import ColumnElement as ColumnElement
|
||||
from .elements import ExpressionClauseList as ExpressionClauseList
|
||||
from .elements import Extract as Extract
|
||||
from .elements import False_ as False_
|
||||
from .elements import FunctionFilter as FunctionFilter
|
||||
from .elements import Grouping as Grouping
|
||||
from .elements import Label as Label
|
||||
from .elements import literal as literal
|
||||
from .elements import literal_column as literal_column
|
||||
from .elements import Null as Null
|
||||
from .elements import Over as Over
|
||||
from .elements import quoted_name as quoted_name
|
||||
from .elements import ReleaseSavepointClause as ReleaseSavepointClause
|
||||
from .elements import RollbackToSavepointClause as RollbackToSavepointClause
|
||||
from .elements import SavepointClause as SavepointClause
|
||||
from .elements import SQLColumnExpression as SQLColumnExpression
|
||||
from .elements import TextClause as TextClause
|
||||
from .elements import True_ as True_
|
||||
from .elements import TryCast as TryCast
|
||||
from .elements import Tuple as Tuple
|
||||
from .elements import TypeClause as TypeClause
|
||||
from .elements import TypeCoerce as TypeCoerce
|
||||
from .elements import UnaryExpression as UnaryExpression
|
||||
from .elements import WithinGroup as WithinGroup
|
||||
from .functions import func as func
|
||||
from .functions import Function as Function
|
||||
from .functions import FunctionElement as FunctionElement
|
||||
from .functions import modifier as modifier
|
||||
from .lambdas import lambda_stmt as lambda_stmt
|
||||
from .lambdas import LambdaElement as LambdaElement
|
||||
from .lambdas import StatementLambdaElement as StatementLambdaElement
|
||||
from .operators import ColumnOperators as ColumnOperators
|
||||
from .operators import custom_op as custom_op
|
||||
from .operators import Operators as Operators
|
||||
from .selectable import Alias as Alias
|
||||
from .selectable import AliasedReturnsRows as AliasedReturnsRows
|
||||
from .selectable import CompoundSelect as CompoundSelect
|
||||
from .selectable import CTE as CTE
|
||||
from .selectable import Exists as Exists
|
||||
from .selectable import FromClause as FromClause
|
||||
from .selectable import FromGrouping as FromGrouping
|
||||
from .selectable import GenerativeSelect as GenerativeSelect
|
||||
from .selectable import HasCTE as HasCTE
|
||||
from .selectable import HasPrefixes as HasPrefixes
|
||||
from .selectable import HasSuffixes as HasSuffixes
|
||||
from .selectable import Join as Join
|
||||
from .selectable import LABEL_STYLE_DEFAULT as LABEL_STYLE_DEFAULT
|
||||
from .selectable import (
|
||||
LABEL_STYLE_DISAMBIGUATE_ONLY as LABEL_STYLE_DISAMBIGUATE_ONLY,
|
||||
)
|
||||
from .selectable import LABEL_STYLE_NONE as LABEL_STYLE_NONE
|
||||
from .selectable import (
|
||||
LABEL_STYLE_TABLENAME_PLUS_COL as LABEL_STYLE_TABLENAME_PLUS_COL,
|
||||
)
|
||||
from .selectable import Lateral as Lateral
|
||||
from .selectable import ReturnsRows as ReturnsRows
|
||||
from .selectable import ScalarSelect as ScalarSelect
|
||||
from .selectable import ScalarValues as ScalarValues
|
||||
from .selectable import Select as Select
|
||||
from .selectable import Selectable as Selectable
|
||||
from .selectable import SelectBase as SelectBase
|
||||
from .selectable import SelectLabelStyle as SelectLabelStyle
|
||||
from .selectable import Subquery as Subquery
|
||||
from .selectable import TableClause as TableClause
|
||||
from .selectable import TableSample as TableSample
|
||||
from .selectable import TableValuedAlias as TableValuedAlias
|
||||
from .selectable import TextAsFrom as TextAsFrom
|
||||
from .selectable import TextualSelect as TextualSelect
|
||||
from .selectable import Values as Values
|
||||
from .visitors import Visitable as Visitable
|
||||
|
||||
nullsfirst = nulls_first
|
||||
"""Synonym for the :func:`.nulls_first` function."""
|
||||
|
||||
|
||||
nullslast = nulls_last
|
||||
"""Synonym for the :func:`.nulls_last` function."""
|
2099
venv/lib/python3.11/site-packages/sqlalchemy/sql/functions.py
Normal file
2099
venv/lib/python3.11/site-packages/sqlalchemy/sql/functions.py
Normal file
File diff suppressed because it is too large
Load Diff
1443
venv/lib/python3.11/site-packages/sqlalchemy/sql/lambdas.py
Normal file
1443
venv/lib/python3.11/site-packages/sqlalchemy/sql/lambdas.py
Normal file
File diff suppressed because it is too large
Load Diff
212
venv/lib/python3.11/site-packages/sqlalchemy/sql/naming.py
Normal file
212
venv/lib/python3.11/site-packages/sqlalchemy/sql/naming.py
Normal file
@ -0,0 +1,212 @@
|
||||
# sql/naming.py
|
||||
# Copyright (C) 2005-2025 the SQLAlchemy authors and contributors
|
||||
# <see AUTHORS file>
|
||||
#
|
||||
# This module is part of SQLAlchemy and is released under
|
||||
# the MIT License: https://www.opensource.org/licenses/mit-license.php
|
||||
# mypy: allow-untyped-defs, allow-untyped-calls
|
||||
|
||||
"""Establish constraint and index naming conventions.
|
||||
|
||||
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import re
|
||||
|
||||
from . import events # noqa
|
||||
from .base import _NONE_NAME
|
||||
from .elements import conv as conv
|
||||
from .schema import CheckConstraint
|
||||
from .schema import Column
|
||||
from .schema import Constraint
|
||||
from .schema import ForeignKeyConstraint
|
||||
from .schema import Index
|
||||
from .schema import PrimaryKeyConstraint
|
||||
from .schema import Table
|
||||
from .schema import UniqueConstraint
|
||||
from .. import event
|
||||
from .. import exc
|
||||
|
||||
|
||||
class ConventionDict:
|
||||
def __init__(self, const, table, convention):
|
||||
self.const = const
|
||||
self._is_fk = isinstance(const, ForeignKeyConstraint)
|
||||
self.table = table
|
||||
self.convention = convention
|
||||
self._const_name = const.name
|
||||
|
||||
def _key_table_name(self):
|
||||
return self.table.name
|
||||
|
||||
def _column_X(self, idx, attrname):
|
||||
if self._is_fk:
|
||||
try:
|
||||
fk = self.const.elements[idx]
|
||||
except IndexError:
|
||||
return ""
|
||||
else:
|
||||
return getattr(fk.parent, attrname)
|
||||
else:
|
||||
cols = list(self.const.columns)
|
||||
try:
|
||||
col = cols[idx]
|
||||
except IndexError:
|
||||
return ""
|
||||
else:
|
||||
return getattr(col, attrname)
|
||||
|
||||
def _key_constraint_name(self):
|
||||
if self._const_name in (None, _NONE_NAME):
|
||||
raise exc.InvalidRequestError(
|
||||
"Naming convention including "
|
||||
"%(constraint_name)s token requires that "
|
||||
"constraint is explicitly named."
|
||||
)
|
||||
if not isinstance(self._const_name, conv):
|
||||
self.const.name = None
|
||||
return self._const_name
|
||||
|
||||
def _key_column_X_key(self, idx):
|
||||
# note this method was missing before
|
||||
# [ticket:3989], meaning tokens like ``%(column_0_key)s`` weren't
|
||||
# working even though documented.
|
||||
return self._column_X(idx, "key")
|
||||
|
||||
def _key_column_X_name(self, idx):
|
||||
return self._column_X(idx, "name")
|
||||
|
||||
def _key_column_X_label(self, idx):
|
||||
return self._column_X(idx, "_ddl_label")
|
||||
|
||||
def _key_referred_table_name(self):
|
||||
fk = self.const.elements[0]
|
||||
refs = fk.target_fullname.split(".")
|
||||
if len(refs) == 3:
|
||||
refschema, reftable, refcol = refs
|
||||
else:
|
||||
reftable, refcol = refs
|
||||
return reftable
|
||||
|
||||
def _key_referred_column_X_name(self, idx):
|
||||
fk = self.const.elements[idx]
|
||||
# note that before [ticket:3989], this method was returning
|
||||
# the specification for the :class:`.ForeignKey` itself, which normally
|
||||
# would be using the ``.key`` of the column, not the name.
|
||||
return fk.column.name
|
||||
|
||||
def __getitem__(self, key):
|
||||
if key in self.convention:
|
||||
return self.convention[key](self.const, self.table)
|
||||
elif hasattr(self, "_key_%s" % key):
|
||||
return getattr(self, "_key_%s" % key)()
|
||||
else:
|
||||
col_template = re.match(r".*_?column_(\d+)(_?N)?_.+", key)
|
||||
if col_template:
|
||||
idx = col_template.group(1)
|
||||
multiples = col_template.group(2)
|
||||
|
||||
if multiples:
|
||||
if self._is_fk:
|
||||
elems = self.const.elements
|
||||
else:
|
||||
elems = list(self.const.columns)
|
||||
tokens = []
|
||||
for idx, elem in enumerate(elems):
|
||||
attr = "_key_" + key.replace("0" + multiples, "X")
|
||||
try:
|
||||
tokens.append(getattr(self, attr)(idx))
|
||||
except AttributeError:
|
||||
raise KeyError(key)
|
||||
sep = "_" if multiples.startswith("_") else ""
|
||||
return sep.join(tokens)
|
||||
else:
|
||||
attr = "_key_" + key.replace(idx, "X")
|
||||
idx = int(idx)
|
||||
if hasattr(self, attr):
|
||||
return getattr(self, attr)(idx)
|
||||
raise KeyError(key)
|
||||
|
||||
|
||||
_prefix_dict = {
|
||||
Index: "ix",
|
||||
PrimaryKeyConstraint: "pk",
|
||||
CheckConstraint: "ck",
|
||||
UniqueConstraint: "uq",
|
||||
ForeignKeyConstraint: "fk",
|
||||
}
|
||||
|
||||
|
||||
def _get_convention(dict_, key):
|
||||
for super_ in key.__mro__:
|
||||
if super_ in _prefix_dict and _prefix_dict[super_] in dict_:
|
||||
return dict_[_prefix_dict[super_]]
|
||||
elif super_ in dict_:
|
||||
return dict_[super_]
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
def _constraint_name_for_table(const, table):
|
||||
metadata = table.metadata
|
||||
convention = _get_convention(metadata.naming_convention, type(const))
|
||||
|
||||
if isinstance(const.name, conv):
|
||||
return const.name
|
||||
elif (
|
||||
convention is not None
|
||||
and not isinstance(const.name, conv)
|
||||
and (
|
||||
const.name is None
|
||||
or "constraint_name" in convention
|
||||
or const.name is _NONE_NAME
|
||||
)
|
||||
):
|
||||
return conv(
|
||||
convention
|
||||
% ConventionDict(const, table, metadata.naming_convention)
|
||||
)
|
||||
elif convention is _NONE_NAME:
|
||||
return None
|
||||
|
||||
|
||||
@event.listens_for(
|
||||
PrimaryKeyConstraint, "_sa_event_column_added_to_pk_constraint"
|
||||
)
|
||||
def _column_added_to_pk_constraint(pk_constraint, col):
|
||||
if pk_constraint._implicit_generated:
|
||||
# only operate upon the "implicit" pk constraint for now,
|
||||
# as we have to force the name to None to reset it. the
|
||||
# "implicit" constraint will only have a naming convention name
|
||||
# if at all.
|
||||
table = pk_constraint.table
|
||||
pk_constraint.name = None
|
||||
newname = _constraint_name_for_table(pk_constraint, table)
|
||||
if newname:
|
||||
pk_constraint.name = newname
|
||||
|
||||
|
||||
@event.listens_for(Constraint, "after_parent_attach")
|
||||
@event.listens_for(Index, "after_parent_attach")
|
||||
def _constraint_name(const, table):
|
||||
if isinstance(table, Column):
|
||||
# this path occurs for a CheckConstraint linked to a Column
|
||||
|
||||
# for column-attached constraint, set another event
|
||||
# to link the column attached to the table as this constraint
|
||||
# associated with the table.
|
||||
event.listen(
|
||||
table,
|
||||
"after_parent_attach",
|
||||
lambda col, table: _constraint_name(const, table),
|
||||
)
|
||||
|
||||
elif isinstance(table, Table):
|
||||
if isinstance(const.name, conv) or const.name is _NONE_NAME:
|
||||
return
|
||||
|
||||
newname = _constraint_name_for_table(const, table)
|
||||
if newname:
|
||||
const.name = newname
|
2623
venv/lib/python3.11/site-packages/sqlalchemy/sql/operators.py
Normal file
2623
venv/lib/python3.11/site-packages/sqlalchemy/sql/operators.py
Normal file
File diff suppressed because it is too large
Load Diff
323
venv/lib/python3.11/site-packages/sqlalchemy/sql/roles.py
Normal file
323
venv/lib/python3.11/site-packages/sqlalchemy/sql/roles.py
Normal file
@ -0,0 +1,323 @@
|
||||
# sql/roles.py
|
||||
# Copyright (C) 2005-2025 the SQLAlchemy authors and contributors
|
||||
# <see AUTHORS file>
|
||||
#
|
||||
# This module is part of SQLAlchemy and is released under
|
||||
# the MIT License: https://www.opensource.org/licenses/mit-license.php
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
from typing import Generic
|
||||
from typing import Optional
|
||||
from typing import TYPE_CHECKING
|
||||
from typing import TypeVar
|
||||
|
||||
from .. import util
|
||||
from ..util.typing import Literal
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from ._typing import _PropagateAttrsType
|
||||
from .elements import Label
|
||||
from .selectable import _SelectIterable
|
||||
from .selectable import FromClause
|
||||
from .selectable import Subquery
|
||||
|
||||
_T = TypeVar("_T", bound=Any)
|
||||
_T_co = TypeVar("_T_co", bound=Any, covariant=True)
|
||||
|
||||
|
||||
class SQLRole:
|
||||
"""Define a "role" within a SQL statement structure.
|
||||
|
||||
Classes within SQL Core participate within SQLRole hierarchies in order
|
||||
to more accurately indicate where they may be used within SQL statements
|
||||
of all types.
|
||||
|
||||
.. versionadded:: 1.4
|
||||
|
||||
"""
|
||||
|
||||
__slots__ = ()
|
||||
allows_lambda = False
|
||||
uses_inspection = False
|
||||
|
||||
|
||||
class UsesInspection:
|
||||
__slots__ = ()
|
||||
_post_inspect: Literal[None] = None
|
||||
uses_inspection = True
|
||||
|
||||
|
||||
class AllowsLambdaRole:
|
||||
__slots__ = ()
|
||||
allows_lambda = True
|
||||
|
||||
|
||||
class HasCacheKeyRole(SQLRole):
|
||||
__slots__ = ()
|
||||
_role_name = "Cacheable Core or ORM object"
|
||||
|
||||
|
||||
class ExecutableOptionRole(SQLRole):
|
||||
__slots__ = ()
|
||||
_role_name = "ExecutionOption Core or ORM object"
|
||||
|
||||
|
||||
class LiteralValueRole(SQLRole):
|
||||
__slots__ = ()
|
||||
_role_name = "Literal Python value"
|
||||
|
||||
|
||||
class ColumnArgumentRole(SQLRole):
|
||||
__slots__ = ()
|
||||
_role_name = "Column expression"
|
||||
|
||||
|
||||
class ColumnArgumentOrKeyRole(ColumnArgumentRole):
|
||||
__slots__ = ()
|
||||
_role_name = "Column expression or string key"
|
||||
|
||||
|
||||
class StrAsPlainColumnRole(ColumnArgumentRole):
|
||||
__slots__ = ()
|
||||
_role_name = "Column expression or string key"
|
||||
|
||||
|
||||
class ColumnListRole(SQLRole):
|
||||
"""Elements suitable for forming comma separated lists of expressions."""
|
||||
|
||||
__slots__ = ()
|
||||
|
||||
|
||||
class StringRole(SQLRole):
|
||||
"""mixin indicating a role that results in strings"""
|
||||
|
||||
__slots__ = ()
|
||||
|
||||
|
||||
class TruncatedLabelRole(StringRole, SQLRole):
|
||||
__slots__ = ()
|
||||
_role_name = "String SQL identifier"
|
||||
|
||||
|
||||
class ColumnsClauseRole(AllowsLambdaRole, UsesInspection, ColumnListRole):
|
||||
__slots__ = ()
|
||||
_role_name = (
|
||||
"Column expression, FROM clause, or other columns clause element"
|
||||
)
|
||||
|
||||
@property
|
||||
def _select_iterable(self) -> _SelectIterable:
|
||||
raise NotImplementedError()
|
||||
|
||||
|
||||
class TypedColumnsClauseRole(Generic[_T_co], SQLRole):
|
||||
"""element-typed form of ColumnsClauseRole"""
|
||||
|
||||
__slots__ = ()
|
||||
|
||||
|
||||
class LimitOffsetRole(SQLRole):
|
||||
__slots__ = ()
|
||||
_role_name = "LIMIT / OFFSET expression"
|
||||
|
||||
|
||||
class ByOfRole(ColumnListRole):
|
||||
__slots__ = ()
|
||||
_role_name = "GROUP BY / OF / etc. expression"
|
||||
|
||||
|
||||
class GroupByRole(AllowsLambdaRole, UsesInspection, ByOfRole):
|
||||
__slots__ = ()
|
||||
# note there's a special case right now where you can pass a whole
|
||||
# ORM entity to group_by() and it splits out. we may not want to keep
|
||||
# this around
|
||||
|
||||
_role_name = "GROUP BY expression"
|
||||
|
||||
|
||||
class OrderByRole(AllowsLambdaRole, ByOfRole):
|
||||
__slots__ = ()
|
||||
_role_name = "ORDER BY expression"
|
||||
|
||||
|
||||
class StructuralRole(SQLRole):
|
||||
__slots__ = ()
|
||||
|
||||
|
||||
class StatementOptionRole(StructuralRole):
|
||||
__slots__ = ()
|
||||
_role_name = "statement sub-expression element"
|
||||
|
||||
|
||||
class OnClauseRole(AllowsLambdaRole, StructuralRole):
|
||||
__slots__ = ()
|
||||
_role_name = (
|
||||
"ON clause, typically a SQL expression or "
|
||||
"ORM relationship attribute"
|
||||
)
|
||||
|
||||
|
||||
class WhereHavingRole(OnClauseRole):
|
||||
__slots__ = ()
|
||||
_role_name = "SQL expression for WHERE/HAVING role"
|
||||
|
||||
|
||||
class ExpressionElementRole(TypedColumnsClauseRole[_T_co]):
|
||||
# note when using generics for ExpressionElementRole,
|
||||
# the generic type needs to be in
|
||||
# sqlalchemy.sql.coercions._impl_lookup mapping also.
|
||||
# these are set up for basic types like int, bool, str, float
|
||||
# right now
|
||||
|
||||
__slots__ = ()
|
||||
_role_name = "SQL expression element"
|
||||
|
||||
def label(self, name: Optional[str]) -> Label[_T]:
|
||||
raise NotImplementedError()
|
||||
|
||||
|
||||
class ConstExprRole(ExpressionElementRole[_T]):
|
||||
__slots__ = ()
|
||||
_role_name = "Constant True/False/None expression"
|
||||
|
||||
|
||||
class LabeledColumnExprRole(ExpressionElementRole[_T]):
|
||||
__slots__ = ()
|
||||
|
||||
|
||||
class BinaryElementRole(ExpressionElementRole[_T]):
|
||||
__slots__ = ()
|
||||
_role_name = "SQL expression element or literal value"
|
||||
|
||||
|
||||
class InElementRole(SQLRole):
|
||||
__slots__ = ()
|
||||
_role_name = (
|
||||
"IN expression list, SELECT construct, or bound parameter object"
|
||||
)
|
||||
|
||||
|
||||
class JoinTargetRole(AllowsLambdaRole, UsesInspection, StructuralRole):
|
||||
__slots__ = ()
|
||||
_role_name = (
|
||||
"Join target, typically a FROM expression, or ORM "
|
||||
"relationship attribute"
|
||||
)
|
||||
|
||||
|
||||
class FromClauseRole(ColumnsClauseRole, JoinTargetRole):
|
||||
__slots__ = ()
|
||||
_role_name = "FROM expression, such as a Table or alias() object"
|
||||
|
||||
_is_subquery = False
|
||||
|
||||
named_with_column: bool
|
||||
|
||||
|
||||
class StrictFromClauseRole(FromClauseRole):
|
||||
__slots__ = ()
|
||||
# does not allow text() or select() objects
|
||||
|
||||
|
||||
class AnonymizedFromClauseRole(StrictFromClauseRole):
|
||||
__slots__ = ()
|
||||
|
||||
if TYPE_CHECKING:
|
||||
|
||||
def _anonymous_fromclause(
|
||||
self, *, name: Optional[str] = None, flat: bool = False
|
||||
) -> FromClause: ...
|
||||
|
||||
|
||||
class ReturnsRowsRole(SQLRole):
|
||||
__slots__ = ()
|
||||
_role_name = (
|
||||
"Row returning expression such as a SELECT, a FROM clause, or an "
|
||||
"INSERT/UPDATE/DELETE with RETURNING"
|
||||
)
|
||||
|
||||
|
||||
class StatementRole(SQLRole):
|
||||
__slots__ = ()
|
||||
_role_name = "Executable SQL or text() construct"
|
||||
|
||||
if TYPE_CHECKING:
|
||||
|
||||
@util.memoized_property
|
||||
def _propagate_attrs(self) -> _PropagateAttrsType: ...
|
||||
|
||||
else:
|
||||
_propagate_attrs = util.EMPTY_DICT
|
||||
|
||||
|
||||
class SelectStatementRole(StatementRole, ReturnsRowsRole):
|
||||
__slots__ = ()
|
||||
_role_name = "SELECT construct or equivalent text() construct"
|
||||
|
||||
def subquery(self) -> Subquery:
|
||||
raise NotImplementedError(
|
||||
"All SelectStatementRole objects should implement a "
|
||||
".subquery() method."
|
||||
)
|
||||
|
||||
|
||||
class HasCTERole(ReturnsRowsRole):
|
||||
__slots__ = ()
|
||||
|
||||
|
||||
class IsCTERole(SQLRole):
|
||||
__slots__ = ()
|
||||
_role_name = "CTE object"
|
||||
|
||||
|
||||
class CompoundElementRole(AllowsLambdaRole, SQLRole):
|
||||
"""SELECT statements inside a CompoundSelect, e.g. UNION, EXTRACT, etc."""
|
||||
|
||||
__slots__ = ()
|
||||
_role_name = (
|
||||
"SELECT construct for inclusion in a UNION or other set construct"
|
||||
)
|
||||
|
||||
|
||||
# TODO: are we using this?
|
||||
class DMLRole(StatementRole):
|
||||
__slots__ = ()
|
||||
|
||||
|
||||
class DMLTableRole(FromClauseRole):
|
||||
__slots__ = ()
|
||||
_role_name = "subject table for an INSERT, UPDATE or DELETE"
|
||||
|
||||
|
||||
class DMLColumnRole(SQLRole):
|
||||
__slots__ = ()
|
||||
_role_name = "SET/VALUES column expression or string key"
|
||||
|
||||
|
||||
class DMLSelectRole(SQLRole):
|
||||
"""A SELECT statement embedded in DML, typically INSERT from SELECT"""
|
||||
|
||||
__slots__ = ()
|
||||
_role_name = "SELECT statement or equivalent textual object"
|
||||
|
||||
|
||||
class DDLRole(StatementRole):
|
||||
__slots__ = ()
|
||||
|
||||
|
||||
class DDLExpressionRole(StructuralRole):
|
||||
__slots__ = ()
|
||||
_role_name = "SQL expression element for DDL constraint"
|
||||
|
||||
|
||||
class DDLConstraintColumnRole(SQLRole):
|
||||
__slots__ = ()
|
||||
_role_name = "String column name or column expression for DDL constraint"
|
||||
|
||||
|
||||
class DDLReferredColumnRole(DDLConstraintColumnRole):
|
||||
__slots__ = ()
|
||||
_role_name = (
|
||||
"String column name or Column object for DDL foreign key constraint"
|
||||
)
|
6219
venv/lib/python3.11/site-packages/sqlalchemy/sql/schema.py
Normal file
6219
venv/lib/python3.11/site-packages/sqlalchemy/sql/schema.py
Normal file
File diff suppressed because it is too large
Load Diff
7183
venv/lib/python3.11/site-packages/sqlalchemy/sql/selectable.py
Normal file
7183
venv/lib/python3.11/site-packages/sqlalchemy/sql/selectable.py
Normal file
File diff suppressed because it is too large
Load Diff
3908
venv/lib/python3.11/site-packages/sqlalchemy/sql/sqltypes.py
Normal file
3908
venv/lib/python3.11/site-packages/sqlalchemy/sql/sqltypes.py
Normal file
File diff suppressed because it is too large
Load Diff
1024
venv/lib/python3.11/site-packages/sqlalchemy/sql/traversals.py
Normal file
1024
venv/lib/python3.11/site-packages/sqlalchemy/sql/traversals.py
Normal file
File diff suppressed because it is too large
Load Diff
2362
venv/lib/python3.11/site-packages/sqlalchemy/sql/type_api.py
Normal file
2362
venv/lib/python3.11/site-packages/sqlalchemy/sql/type_api.py
Normal file
File diff suppressed because it is too large
Load Diff
1487
venv/lib/python3.11/site-packages/sqlalchemy/sql/util.py
Normal file
1487
venv/lib/python3.11/site-packages/sqlalchemy/sql/util.py
Normal file
File diff suppressed because it is too large
Load Diff
1167
venv/lib/python3.11/site-packages/sqlalchemy/sql/visitors.py
Normal file
1167
venv/lib/python3.11/site-packages/sqlalchemy/sql/visitors.py
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user