# the MIT License: https://www.opensource.org/licenses/mit-license.php
from . import util as _util
-from .engine import create_engine
-from .engine import create_mock_engine
-from .engine import engine_from_config
-from .inspection import inspect
-from .schema import BLANK_SCHEMA
-from .schema import CheckConstraint
-from .schema import Column
-from .schema import ColumnDefault
-from .schema import Computed
-from .schema import Constraint
-from .schema import DDL
-from .schema import DefaultClause
-from .schema import FetchedValue
-from .schema import ForeignKey
-from .schema import ForeignKeyConstraint
-from .schema import Identity
-from .schema import Index
-from .schema import MetaData
-from .schema import PrimaryKeyConstraint
-from .schema import Sequence
-from .schema import Table
-from .schema import UniqueConstraint
-from .sql import alias
-from .sql import all_
-from .sql import and_
-from .sql import any_
-from .sql import asc
-from .sql import between
-from .sql import bindparam
-from .sql import case
-from .sql import cast
-from .sql import collate
-from .sql import column
-from .sql import delete
-from .sql import desc
-from .sql import distinct
-from .sql import except_
-from .sql import except_all
-from .sql import exists
-from .sql import extract
-from .sql import false
-from .sql import func
-from .sql import funcfilter
-from .sql import insert
-from .sql import intersect
-from .sql import intersect_all
-from .sql import join
-from .sql import LABEL_STYLE_DEFAULT
-from .sql import LABEL_STYLE_DISAMBIGUATE_ONLY
-from .sql import LABEL_STYLE_NONE
-from .sql import LABEL_STYLE_TABLENAME_PLUS_COL
-from .sql import lambda_stmt
-from .sql import lateral
-from .sql import literal
-from .sql import literal_column
-from .sql import modifier
-from .sql import not_
-from .sql import null
-from .sql import nulls_first
-from .sql import nulls_last
-from .sql import nullsfirst
-from .sql import nullslast
-from .sql import or_
-from .sql import outerjoin
-from .sql import outparam
-from .sql import over
-from .sql import select
-from .sql import table
-from .sql import tablesample
-from .sql import text
-from .sql import true
-from .sql import tuple_
-from .sql import type_coerce
-from .sql import union
-from .sql import union_all
-from .sql import update
-from .sql import values
-from .sql import within_group
-from .types import ARRAY
-from .types import BIGINT
-from .types import BigInteger
-from .types import BINARY
-from .types import BLOB
-from .types import BOOLEAN
-from .types import Boolean
-from .types import CHAR
-from .types import CLOB
-from .types import DATE
-from .types import Date
-from .types import DATETIME
-from .types import DateTime
-from .types import DECIMAL
-from .types import Enum
-from .types import FLOAT
-from .types import Float
-from .types import INT
-from .types import INTEGER
-from .types import Integer
-from .types import Interval
-from .types import JSON
-from .types import LargeBinary
-from .types import NCHAR
-from .types import NUMERIC
-from .types import Numeric
-from .types import NVARCHAR
-from .types import PickleType
-from .types import REAL
-from .types import SMALLINT
-from .types import SmallInteger
-from .types import String
-from .types import TEXT
-from .types import Text
-from .types import TIME
-from .types import Time
-from .types import TIMESTAMP
-from .types import TupleType
-from .types import TypeDecorator
-from .types import Unicode
-from .types import UnicodeText
-from .types import VARBINARY
-from .types import VARCHAR
+from .engine import create_engine as create_engine
+from .engine import create_mock_engine as create_mock_engine
+from .engine import engine_from_config as engine_from_config
+from .inspection import inspect as inspect
+from .schema import BLANK_SCHEMA as BLANK_SCHEMA
+from .schema import CheckConstraint as CheckConstraint
+from .schema import Column as Column
+from .schema import ColumnDefault as ColumnDefault
+from .schema import Computed as Computed
+from .schema import Constraint as Constraint
+from .schema import DDL as DDL
+from .schema import DefaultClause as DefaultClause
+from .schema import FetchedValue as FetchedValue
+from .schema import ForeignKey as ForeignKey
+from .schema import ForeignKeyConstraint as ForeignKeyConstraint
+from .schema import Identity as Identity
+from .schema import Index as Index
+from .schema import MetaData as MetaData
+from .schema import PrimaryKeyConstraint as PrimaryKeyConstraint
+from .schema import Sequence as Sequence
+from .schema import Table as Table
+from .schema import UniqueConstraint as UniqueConstraint
+from .sql import alias as alias
+from .sql import all_ as all_
+from .sql import and_ as and_
+from .sql import any_ as any_
+from .sql import asc as asc
+from .sql import between as between
+from .sql import bindparam as bindparam
+from .sql import case as case
+from .sql import cast as cast
+from .sql import collate as collate
+from .sql import column as column
+from .sql import delete as delete
+from .sql import desc as desc
+from .sql import distinct as distinct
+from .sql import except_ as except_
+from .sql import except_all as except_all
+from .sql import exists as exists
+from .sql import extract as extract
+from .sql import false as false
+from .sql import func as func
+from .sql import funcfilter as funcfilter
+from .sql import insert as insert
+from .sql import intersect as intersect
+from .sql import intersect_all as intersect_all
+from .sql import join as join
+from .sql import label as label
+from .sql import LABEL_STYLE_DEFAULT as LABEL_STYLE_DEFAULT
+from .sql import LABEL_STYLE_DISAMBIGUATE_ONLY as LABEL_STYLE_DISAMBIGUATE_ONLY
+from .sql import LABEL_STYLE_NONE as LABEL_STYLE_NONE
+from .sql import lambda_stmt as lambda_stmt
+from .sql import lateral as lateral
+from .sql import literal as literal
+from .sql import literal_column as literal_column
+from .sql import modifier as modifier
+from .sql import not_ as not_
+from .sql import null as null
+from .sql import nulls_first as nulls_first
+from .sql import nulls_last as nulls_last
+from .sql import nullsfirst as nullsfirst
+from .sql import nullslast as nullslast
+from .sql import or_ as or_
+from .sql import outerjoin as outerjoin
+from .sql import outparam as outparam
+from .sql import over as over
+from .sql import select as select
+from .sql import table as table
+from .sql import tablesample as tablesample
+from .sql import text as text
+from .sql import true as true
+from .sql import tuple_ as tuple_
+from .sql import type_coerce as type_coerce
+from .sql import union as union
+from .sql import union_all as union_all
+from .sql import update as update
+from .sql import values as values
+from .sql import within_group as within_group
+from .types import ARRAY as ARRAY
+from .types import BIGINT as BIGINT
+from .types import BigInteger as BigInteger
+from .types import BINARY as BINARY
+from .types import BLOB as BLOB
+from .types import BOOLEAN as BOOLEAN
+from .types import Boolean as Boolean
+from .types import CHAR as CHAR
+from .types import CLOB as CLOB
+from .types import DATE as DATE
+from .types import Date as Date
+from .types import DATETIME as DATETIME
+from .types import DateTime as DateTime
+from .types import DECIMAL as DECIMAL
+from .types import Enum as Enum
+from .types import FLOAT as FLOAT
+from .types import Float as Float
+from .types import INT as INT
+from .types import INTEGER as INTEGER
+from .types import Integer as Integer
+from .types import Interval as Interval
+from .types import JSON as JSON
+from .types import LargeBinary as LargeBinary
+from .types import NCHAR as NCHAR
+from .types import NUMERIC as NUMERIC
+from .types import Numeric as Numeric
+from .types import NVARCHAR as NVARCHAR
+from .types import PickleType as PickleType
+from .types import REAL as REAL
+from .types import SMALLINT as SMALLINT
+from .types import SmallInteger as SmallInteger
+from .types import String as String
+from .types import TEXT as TEXT
+from .types import Text as Text
+from .types import TIME as TIME
+from .types import Time as Time
+from .types import TIMESTAMP as TIMESTAMP
+from .types import TupleType as TupleType
+from .types import TypeDecorator as TypeDecorator
+from .types import Unicode as Unicode
+from .types import UnicodeText as UnicodeText
+from .types import VARBINARY as VARBINARY
+from .types import VARCHAR as VARCHAR
+
+if True:
+ # work around zimports bug
+ from .sql import (
+ LABEL_STYLE_TABLENAME_PLUS_COL as LABEL_STYLE_TABLENAME_PLUS_COL,
+ )
__version__ = "2.0.0b1"
def __go(lcls):
- global __all__
-
- from . import events
from . import util as _sa_util
- import inspect as _inspect
-
- __all__ = sorted(
- name
- for name, obj in lcls.items()
- if not (name.startswith("_") or _inspect.ismodule(obj))
- )
-
_sa_util.preloaded.import_prefix("sqlalchemy")
from . import exc
from ...types import TEXT
from ...types import VARCHAR
from ...util import update_wrapper
-from ...util.langhelpers import public_factory
# https://sqlserverbuilds.blogspot.com/
__visit_name__ = "SQL_VARIANT"
-class TryCast(sql.elements.Cast):
- """Represent a SQL Server TRY_CAST expression."""
+def try_cast(*arg, **kw):
+ """Create a TRY_CAST expression.
- __visit_name__ = "try_cast"
+ :class:`.TryCast` is a subclass of SQLAlchemy's :class:`.Cast`
+ construct, and works in the same way, except that the SQL expression
+ rendered is "TRY_CAST" rather than "CAST"::
- stringify_dialect = "mssql"
- inherit_cache = True
+ from sqlalchemy import select
+ from sqlalchemy import Numeric
+ from sqlalchemy.dialects.mssql import try_cast
- def __init__(self, *arg, **kw):
- """Create a TRY_CAST expression.
+ stmt = select(
+ try_cast(product_table.c.unit_price, Numeric(10, 4))
+ )
- :class:`.TryCast` is a subclass of SQLAlchemy's :class:`.Cast`
- construct, and works in the same way, except that the SQL expression
- rendered is "TRY_CAST" rather than "CAST"::
+ The above would render::
- from sqlalchemy import select
- from sqlalchemy import Numeric
- from sqlalchemy.dialects.mssql import try_cast
+ SELECT TRY_CAST (product_table.unit_price AS NUMERIC(10, 4))
+ FROM product_table
- stmt = select(
- try_cast(product_table.c.unit_price, Numeric(10, 4))
- )
+ .. versionadded:: 1.3.7
- The above would render::
+ """
+ return TryCast(*arg, **kw)
- SELECT TRY_CAST (product_table.unit_price AS NUMERIC(10, 4))
- FROM product_table
- .. versionadded:: 1.3.7
+class TryCast(sql.elements.Cast):
+ """Represent a SQL Server TRY_CAST expression."""
- """
- super(TryCast, self).__init__(*arg, **kw)
+ __visit_name__ = "try_cast"
+ stringify_dialect = "mssql"
+ inherit_cache = True
-try_cast = public_factory(TryCast, ".dialects.mssql.try_cast")
# old names.
MSDateTime = _MSDateTime
from ...sql.dml import Insert as StandardInsert
from ...sql.elements import ClauseElement
from ...sql.expression import alias
-from ...util.langhelpers import public_factory
__all__ = ("Insert", "insert")
+def insert(table):
+ """Construct a MySQL/MariaDB-specific variant :class:`_mysql.Insert`
+ construct.
+
+ .. container:: inherited_member
+
+ The :func:`sqlalchemy.dialects.mysql.insert` function creates
+ a :class:`sqlalchemy.dialects.mysql.Insert`. This class is based
+ on the dialect-agnostic :class:`_sql.Insert` construct which may
+ be constructed using the :func:`_sql.insert` function in
+ SQLAlchemy Core.
+
+ The :class:`_mysql.Insert` construct includes additional methods
+ :meth:`_mysql.Insert.on_duplicate_key_update`.
+
+ """
+ return Insert(table)
+
+
SelfInsert = typing.TypeVar("SelfInsert", bound="Insert")
return self
-insert = public_factory(
- Insert, ".dialects.mysql.insert", ".dialects.mysql.Insert"
-)
-
-
class OnDuplicateClause(ClauseElement):
__visit_name__ = "on_duplicate_key_update"
coercions.expect(roles.ExpressionElementRole, c) for c in clauses
]
- super(array, self).__init__(*clauses, **kw)
-
self._type_tuple = [arg.type for arg in clauses]
main_type = kw.pop(
"type_",
self._type_tuple[0] if self._type_tuple else sqltypes.NULLTYPE,
)
+ super(array, self).__init__(*clauses, **kw)
if isinstance(main_type, ARRAY):
self.type = ARRAY(
from ...sql.dml import Insert as StandardInsert
from ...sql.elements import ClauseElement
from ...sql.expression import alias
-from ...util.langhelpers import public_factory
__all__ = ("Insert", "insert")
+
+def insert(table):
+ """Construct a PostgreSQL-specific variant :class:`_postgresql.Insert`
+ construct.
+
+ .. container:: inherited_member
+
+ The :func:`sqlalchemy.dialects.postgresql.insert` function creates
+ a :class:`sqlalchemy.dialects.postgresql.Insert`. This class is based
+ on the dialect-agnostic :class:`_sql.Insert` construct which may
+ be constructed using the :func:`_sql.insert` function in
+ SQLAlchemy Core.
+
+ The :class:`_postgresql.Insert` construct includes additional methods
+ :meth:`_postgresql.Insert.on_conflict_do_update`,
+ :meth:`_postgresql.Insert.on_conflict_do_nothing`.
+
+ """
+ return Insert(table)
+
+
SelfInsert = typing.TypeVar("SelfInsert", bound="Insert")
return self
-insert = public_factory(
- Insert, ".dialects.postgresql.insert", ".dialects.postgresql.Insert"
-)
-
-
class OnConflictClause(ClauseElement):
stringify_dialect = "postgresql"
from ...sql.dml import Insert as StandardInsert
from ...sql.elements import ClauseElement
from ...sql.expression import alias
-from ...util.langhelpers import public_factory
__all__ = ("Insert", "insert")
+
+def insert(table):
+ """Construct a sqlite-specific variant :class:`_sqlite.Insert`
+ construct.
+
+ .. container:: inherited_member
+
+ The :func:`sqlalchemy.dialects.sqlite.insert` function creates
+ a :class:`sqlalchemy.dialects.sqlite.Insert`. This class is based
+ on the dialect-agnostic :class:`_sql.Insert` construct which may
+ be constructed using the :func:`_sql.insert` function in
+ SQLAlchemy Core.
+
+ The :class:`_sqlite.Insert` construct includes additional methods
+ :meth:`_sqlite.Insert.on_conflict_do_update`,
+ :meth:`_sqlite.Insert.on_conflict_do_nothing`.
+
+ """
+ return Insert(table)
+
+
SelfInsert = typing.TypeVar("SelfInsert", bound="Insert")
return self
-insert = public_factory(
- Insert, ".dialects.sqlite.insert", ".dialects.sqlite.Insert"
-)
-
-
class OnConflictClause(ClauseElement):
stringify_dialect = "sqlite"
"""Future 2.0 API features.
"""
-from .engine import Connection
-from .engine import create_engine
-from .engine import Engine
-from ..sql.selectable import Select
-from ..util.langhelpers import public_factory
-
-
-select = public_factory(Select._create, ".future.select")
+from .engine import Connection as Connection
+from .engine import create_engine as create_engine
+from .engine import Engine as Engine
+from ..sql._selectable_constructors import select as select
"""
-from . import exc
+from . import exc as exc
from . import mapper as mapperlib
-from . import strategy_options
-from .attributes import AttributeEvent
-from .attributes import InstrumentedAttribute
-from .attributes import Mapped
-from .attributes import QueryableAttribute
-from .context import QueryContext
-from .decl_api import as_declarative
-from .decl_api import declarative_base
-from .decl_api import declarative_mixin
-from .decl_api import DeclarativeMeta
-from .decl_api import declared_attr
-from .decl_api import has_inherited_table
-from .decl_api import registry
-from .decl_api import synonym_for
-from .descriptor_props import CompositeProperty
-from .descriptor_props import SynonymProperty
-from .identity import IdentityMap
-from .instrumentation import ClassManager
-from .interfaces import EXT_CONTINUE
-from .interfaces import EXT_SKIP
-from .interfaces import EXT_STOP
-from .interfaces import InspectionAttr
-from .interfaces import InspectionAttrInfo
-from .interfaces import MANYTOMANY
-from .interfaces import MANYTOONE
-from .interfaces import MapperProperty
-from .interfaces import NOT_EXTENSION
-from .interfaces import ONETOMANY
-from .interfaces import PropComparator
-from .interfaces import UserDefinedOption
-from .loading import merge_frozen_result
-from .loading import merge_result
-from .mapper import class_mapper
-from .mapper import configure_mappers
-from .mapper import Mapper
-from .mapper import reconstructor
-from .mapper import validates
-from .properties import ColumnProperty
-from .query import AliasOption
-from .query import FromStatement
-from .query import Query
-from .relationships import foreign
-from .relationships import RelationshipProperty
-from .relationships import remote
-from .scoping import scoped_session
-from .session import close_all_sessions
-from .session import make_transient
-from .session import make_transient_to_detached
-from .session import object_session
-from .session import ORMExecuteState
-from .session import Session
-from .session import sessionmaker
-from .session import SessionTransaction
-from .state import AttributeState
-from .state import InstanceState
-from .strategy_options import contains_eager
-from .strategy_options import defaultload
-from .strategy_options import defer
-from .strategy_options import immediateload
-from .strategy_options import joinedload
-from .strategy_options import lazyload
-from .strategy_options import Load
-from .strategy_options import load_only
-from .strategy_options import noload
-from .strategy_options import raiseload
-from .strategy_options import selectin_polymorphic
-from .strategy_options import selectinload
-from .strategy_options import subqueryload
-from .strategy_options import undefer
-from .strategy_options import undefer_group
-from .strategy_options import with_expression
-from .unitofwork import UOWTransaction
-from .util import aliased
-from .util import Bundle
-from .util import CascadeOptions
-from .util import join
-from .util import LoaderCriteriaOption
-from .util import object_mapper
-from .util import outerjoin
-from .util import polymorphic_union
-from .util import was_deleted
-from .util import with_parent
-from .util import with_polymorphic
-from .. import sql as _sql
+from . import strategy_options as strategy_options
+from ._orm_constructors import _mapper_fn as mapper
+from ._orm_constructors import backref as backref
+from ._orm_constructors import clear_mappers as clear_mappers
+from ._orm_constructors import column_property as column_property
+from ._orm_constructors import composite as composite
+from ._orm_constructors import contains_alias as contains_alias
+from ._orm_constructors import create_session as create_session
+from ._orm_constructors import deferred as deferred
+from ._orm_constructors import dynamic_loader as dynamic_loader
+from ._orm_constructors import query_expression as query_expression
+from ._orm_constructors import relationship as relationship
+from ._orm_constructors import synonym as synonym
+from ._orm_constructors import with_loader_criteria as with_loader_criteria
+from .attributes import AttributeEvent as AttributeEvent
+from .attributes import InstrumentedAttribute as InstrumentedAttribute
+from .attributes import Mapped as Mapped
+from .attributes import QueryableAttribute as QueryableAttribute
+from .context import QueryContext as QueryContext
+from .decl_api import as_declarative as as_declarative
+from .decl_api import declarative_base as declarative_base
+from .decl_api import declarative_mixin as declarative_mixin
+from .decl_api import DeclarativeMeta as DeclarativeMeta
+from .decl_api import declared_attr as declared_attr
+from .decl_api import has_inherited_table as has_inherited_table
+from .decl_api import registry as registry
+from .decl_api import synonym_for as synonym_for
+from .descriptor_props import CompositeProperty as CompositeProperty
+from .descriptor_props import SynonymProperty as SynonymProperty
+from .dynamic import AppenderQuery as AppenderQuery
+from .events import AttributeEvents as AttributeEvents
+from .events import InstanceEvents as InstanceEvents
+from .events import InstrumentationEvents as InstrumentationEvents
+from .events import MapperEvents as MapperEvents
+from .events import QueryEvents as QueryEvents
+from .events import SessionEvents as SessionEvents
+from .identity import IdentityMap as IdentityMap
+from .instrumentation import ClassManager as ClassManager
+from .interfaces import EXT_CONTINUE as EXT_CONTINUE
+from .interfaces import EXT_SKIP as EXT_SKIP
+from .interfaces import EXT_STOP as EXT_STOP
+from .interfaces import InspectionAttr as InspectionAttr
+from .interfaces import InspectionAttrInfo as InspectionAttrInfo
+from .interfaces import MANYTOMANY as MANYTOMANY
+from .interfaces import MANYTOONE as MANYTOONE
+from .interfaces import MapperProperty as MapperProperty
+from .interfaces import NOT_EXTENSION as NOT_EXTENSION
+from .interfaces import ONETOMANY as ONETOMANY
+from .interfaces import PropComparator as PropComparator
+from .interfaces import UserDefinedOption as UserDefinedOption
+from .loading import merge_frozen_result as merge_frozen_result
+from .loading import merge_result as merge_result
+from .mapper import class_mapper as class_mapper
+from .mapper import configure_mappers as configure_mappers
+from .mapper import Mapper as Mapper
+from .mapper import reconstructor as reconstructor
+from .mapper import validates as validates
+from .properties import ColumnProperty as ColumnProperty
+from .query import AliasOption as AliasOption
+from .query import FromStatement as FromStatement
+from .query import Query as Query
+from .relationships import foreign as foreign
+from .relationships import RelationshipProperty as RelationshipProperty
+from .relationships import remote as remote
+from .scoping import scoped_session as scoped_session
+from .session import close_all_sessions as close_all_sessions
+from .session import make_transient as make_transient
+from .session import make_transient_to_detached as make_transient_to_detached
+from .session import object_session as object_session
+from .session import ORMExecuteState as ORMExecuteState
+from .session import Session as Session
+from .session import sessionmaker as sessionmaker
+from .session import SessionTransaction as SessionTransaction
+from .state import AttributeState as AttributeState
+from .state import InstanceState as InstanceState
+from .strategy_options import contains_eager as contains_eager
+from .strategy_options import defaultload as defaultload
+from .strategy_options import defer as defer
+from .strategy_options import immediateload as immediateload
+from .strategy_options import joinedload as joinedload
+from .strategy_options import lazyload as lazyload
+from .strategy_options import Load as Load
+from .strategy_options import load_only as load_only
+from .strategy_options import noload as noload
+from .strategy_options import raiseload as raiseload
+from .strategy_options import selectin_polymorphic as selectin_polymorphic
+from .strategy_options import selectinload as selectinload
+from .strategy_options import subqueryload as subqueryload
+from .strategy_options import undefer as undefer
+from .strategy_options import undefer_group as undefer_group
+from .strategy_options import with_expression as with_expression
+from .unitofwork import UOWTransaction as UOWTransaction
+from .util import aliased as aliased
+from .util import Bundle as Bundle
+from .util import CascadeOptions as CascadeOptions
+from .util import join as join
+from .util import LoaderCriteriaOption as LoaderCriteriaOption
+from .util import object_mapper as object_mapper
+from .util import outerjoin as outerjoin
+from .util import polymorphic_union as polymorphic_union
+from .util import was_deleted as was_deleted
+from .util import with_parent as with_parent
+from .util import with_polymorphic as with_polymorphic
from .. import util as _sa_util
-from ..exc import InvalidRequestError
-from ..util.langhelpers import public_factory
-
-
-def create_session(bind=None, **kwargs):
- r"""Create a new :class:`.Session`
- with no automation enabled by default.
-
- This function is used primarily for testing. The usual
- route to :class:`.Session` creation is via its constructor
- or the :func:`.sessionmaker` function.
-
- :param bind: optional, a single Connectable to use for all
- database access in the created
- :class:`~sqlalchemy.orm.session.Session`.
-
- :param \*\*kwargs: optional, passed through to the
- :class:`.Session` constructor.
-
- :returns: an :class:`~sqlalchemy.orm.session.Session` instance
-
- The defaults of create_session() are the opposite of that of
- :func:`sessionmaker`; ``autoflush`` and ``expire_on_commit`` are
- False.
-
- Usage::
-
- >>> from sqlalchemy.orm import create_session
- >>> session = create_session()
-
- It is recommended to use :func:`sessionmaker` instead of
- create_session().
-
- """
-
- kwargs.setdefault("autoflush", False)
- kwargs.setdefault("expire_on_commit", False)
- return Session(bind=bind, **kwargs)
-
-
-with_loader_criteria = public_factory(LoaderCriteriaOption, ".orm")
-
-relationship = public_factory(RelationshipProperty, ".orm.relationship")
-
-
-def mapper(*arg, **kw):
- """Placeholder for the now-removed ``mapper()`` function.
-
- Classical mappings should be performed using the
- :meth:`_orm.registry.map_imperatively` method.
-
- This symbol remains in SQLAlchemy 2.0 to suit the deprecated use case
- of using the ``mapper()`` function as a target for ORM event listeners,
- which failed to be marked as deprecated in the 1.4 series.
-
- Global ORM mapper listeners should instead use the :class:`_orm.Mapper`
- class as the target.
-
- .. versionchanged:: 2.0 The ``mapper()`` function was removed; the
- symbol remains temporarily as a placeholder for the event listening
- use case.
-
- """
- raise InvalidRequestError(
- "The 'sqlalchemy.orm.mapper()' function is removed as of "
- "SQLAlchemy 2.0. Use the "
- "'sqlalchemy.orm.registry.map_imperatively()` "
- "method of the ``sqlalchemy.orm.registry`` class to perform "
- "classical mapping."
- )
-
-
-def dynamic_loader(argument, **kw):
- """Construct a dynamically-loading mapper property.
-
- This is essentially the same as
- using the ``lazy='dynamic'`` argument with :func:`relationship`::
-
- dynamic_loader(SomeClass)
-
- # is the same as
-
- relationship(SomeClass, lazy="dynamic")
-
- See the section :ref:`dynamic_relationship` for more details
- on dynamic loading.
-
- """
- kw["lazy"] = "dynamic"
- return relationship(argument, **kw)
-
-
-column_property = public_factory(ColumnProperty, ".orm.column_property")
-composite = public_factory(CompositeProperty, ".orm.composite")
-
-
-def backref(name, **kwargs):
- """Create a back reference with explicit keyword arguments, which are the
- same arguments one can send to :func:`relationship`.
-
- Used with the ``backref`` keyword argument to :func:`relationship` in
- place of a string argument, e.g.::
-
- 'items':relationship(
- SomeItem, backref=backref('parent', lazy='subquery'))
-
- .. seealso::
-
- :ref:`relationships_backref`
-
- """
-
- return (name, kwargs)
-
-
-def deferred(*columns, **kw):
- r"""Indicate a column-based mapped attribute that by default will
- not load unless accessed.
-
- :param \*columns: columns to be mapped. This is typically a single
- :class:`_schema.Column` object,
- however a collection is supported in order
- to support multiple columns mapped under the same attribute.
-
- :param raiseload: boolean, if True, indicates an exception should be raised
- if the load operation is to take place.
-
- .. versionadded:: 1.4
-
- .. seealso::
-
- :ref:`deferred_raiseload`
-
- :param \**kw: additional keyword arguments passed to
- :class:`.ColumnProperty`.
-
- .. seealso::
-
- :ref:`deferred`
-
- """
- return ColumnProperty(deferred=True, *columns, **kw)
-
-
-def query_expression(default_expr=_sql.null()):
- """Indicate an attribute that populates from a query-time SQL expression.
-
- :param default_expr: Optional SQL expression object that will be used in
- all cases if not assigned later with :func:`_orm.with_expression`.
- E.g.::
-
- from sqlalchemy.sql import literal
-
- class C(Base):
- #...
- my_expr = query_expression(literal(1))
-
- .. versionadded:: 1.3.18
-
-
- .. versionadded:: 1.2
-
- .. seealso::
-
- :ref:`mapper_querytime_expression`
-
- """
- prop = ColumnProperty(default_expr)
- prop.strategy_key = (("query_expression", True),)
- return prop
-
-
-synonym = public_factory(SynonymProperty, ".orm.synonym")
-
-
-def clear_mappers():
- """Remove all mappers from all classes.
-
- .. versionchanged:: 1.4 This function now locates all
- :class:`_orm.registry` objects and calls upon the
- :meth:`_orm.registry.dispose` method of each.
-
- This function removes all instrumentation from classes and disposes
- of their associated mappers. Once called, the classes are unmapped
- and can be later re-mapped with new mappers.
-
- :func:`.clear_mappers` is *not* for normal use, as there is literally no
- valid usage for it outside of very specific testing scenarios. Normally,
- mappers are permanent structural components of user-defined classes, and
- are never discarded independently of their class. If a mapped class
- itself is garbage collected, its mapper is automatically disposed of as
- well. As such, :func:`.clear_mappers` is only for usage in test suites
- that re-use the same classes with different mappings, which is itself an
- extremely rare use case - the only such use case is in fact SQLAlchemy's
- own test suite, and possibly the test suites of other ORM extension
- libraries which intend to test various combinations of mapper construction
- upon a fixed set of classes.
-
- """
-
- mapperlib._dispose_registries(mapperlib._all_registries(), False)
-
-
-contains_alias = public_factory(AliasOption, ".orm.contains_alias")
-
-if True:
- from .events import AttributeEvents
- from .events import MapperEvents
- from .events import InstanceEvents
- from .events import InstrumentationEvents
- from .events import QueryEvents
- from .events import SessionEvents
def __go(lcls):
- global __all__
- global AppenderQuery
- from .. import util as sa_util
- from . import dynamic
- from . import events
- from . import loading
- import inspect as _inspect
-
- from .dynamic import AppenderQuery
-
- __all__ = sorted(
- name
- for name, obj in lcls.items()
- if not (name.startswith("_") or _inspect.ismodule(obj))
- )
_sa_util.preloaded.import_prefix("sqlalchemy.orm")
_sa_util.preloaded.import_prefix("sqlalchemy.ext")
--- /dev/null
+# orm/_orm_constructors.py
+# Copyright (C) 2005-2022 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
+
+import typing
+from typing import Callable
+from typing import Type
+from typing import Union
+
+from . import mapper as mapperlib
+from .descriptor_props import CompositeProperty
+from .descriptor_props import SynonymProperty
+from .properties import ColumnProperty
+from .query import AliasOption
+from .relationships import RelationshipProperty
+from .session import Session
+from .util import LoaderCriteriaOption
+from .. import sql
+from .. import util
+from ..exc import InvalidRequestError
+
+_RC = typing.TypeVar("_RC")
+_T = typing.TypeVar("_T")
+
+
+@util.deprecated(
+ "1.4",
+ "The :class:`.AliasOption` object is not necessary "
+ "for entities to be matched up to a query that is established "
+ "via :meth:`.Query.from_statement` and now does nothing.",
+)
+def contains_alias(alias) -> "AliasOption":
+ r"""Return a :class:`.MapperOption` that will indicate to the
+ :class:`_query.Query`
+ that the main table has been aliased.
+
+ """
+ return AliasOption(alias)
+
+
+def column_property(
+ column: sql.ColumnElement[_T], *additional_columns, **kwargs
+) -> "ColumnProperty[_T]":
+ r"""Provide a column-level property for use with a mapping.
+
+ Column-based properties can normally be applied to the mapper's
+ ``properties`` dictionary using the :class:`_schema.Column`
+ element directly.
+ Use this function when the given column is not directly present within
+ the mapper's selectable; examples include SQL expressions, functions,
+ and scalar SELECT queries.
+
+ The :func:`_orm.column_property` function returns an instance of
+ :class:`.ColumnProperty`.
+
+ Columns that aren't present in the mapper's selectable won't be
+ persisted by the mapper and are effectively "read-only" attributes.
+
+ :param \*cols:
+ list of Column objects to be mapped.
+
+ :param active_history=False:
+ When ``True``, indicates that the "previous" value for a
+ scalar attribute should be loaded when replaced, if not
+ already loaded. Normally, history tracking logic for
+ simple non-primary-key scalar values only needs to be
+ aware of the "new" value in order to perform a flush. This
+ flag is available for applications that make use of
+ :func:`.attributes.get_history` or :meth:`.Session.is_modified`
+ which also need to know
+ the "previous" value of the attribute.
+
+ :param comparator_factory: a class which extends
+ :class:`.ColumnProperty.Comparator` which provides custom SQL
+ clause generation for comparison operations.
+
+ :param group:
+ a group name for this property when marked as deferred.
+
+ :param deferred:
+ when True, the column property is "deferred", meaning that
+ it does not load immediately, and is instead loaded when the
+ attribute is first accessed on an instance. See also
+ :func:`~sqlalchemy.orm.deferred`.
+
+ :param doc:
+ optional string that will be applied as the doc on the
+ class-bound descriptor.
+
+ :param expire_on_flush=True:
+ Disable expiry on flush. A column_property() which refers
+ to a SQL expression (and not a single table-bound column)
+ is considered to be a "read only" property; populating it
+ has no effect on the state of data, and it can only return
+ database state. For this reason a column_property()'s value
+ is expired whenever the parent object is involved in a
+ flush, that is, has any kind of "dirty" state within a flush.
+ Setting this parameter to ``False`` will have the effect of
+ leaving any existing value present after the flush proceeds.
+ Note however that the :class:`.Session` with default expiration
+ settings still expires
+ all attributes after a :meth:`.Session.commit` call, however.
+
+ :param info: Optional data dictionary which will be populated into the
+ :attr:`.MapperProperty.info` attribute of this object.
+
+ :param raiseload: if True, indicates the column should raise an error
+ when undeferred, rather than loading the value. This can be
+ altered at query time by using the :func:`.deferred` option with
+ raiseload=False.
+
+ .. versionadded:: 1.4
+
+ .. seealso::
+
+ :ref:`deferred_raiseload`
+
+ .. seealso::
+
+ :ref:`column_property_options` - to map columns while including
+ mapping options
+
+ :ref:`mapper_column_property_sql_expressions` - to map SQL
+ expressions
+
+ """
+ return ColumnProperty(column, *additional_columns, **kwargs)
+
+
+def composite(class_: Type[_T], *attrs, **kwargs) -> "CompositeProperty[_T]":
+ r"""Return a composite column-based property for use with a Mapper.
+
+ See the mapping documentation section :ref:`mapper_composite` for a
+ full usage example.
+
+ The :class:`.MapperProperty` returned by :func:`.composite`
+ is the :class:`.CompositeProperty`.
+
+ :param class\_:
+ The "composite type" class, or any classmethod or callable which
+ will produce a new instance of the composite object given the
+ column values in order.
+
+ :param \*cols:
+ List of Column objects to be mapped.
+
+ :param active_history=False:
+ When ``True``, indicates that the "previous" value for a
+ scalar attribute should be loaded when replaced, if not
+ already loaded. See the same flag on :func:`.column_property`.
+
+ :param group:
+ A group name for this property when marked as deferred.
+
+ :param deferred:
+ When True, the column property is "deferred", meaning that it does
+ not load immediately, and is instead loaded when the attribute is
+ first accessed on an instance. See also
+ :func:`~sqlalchemy.orm.deferred`.
+
+ :param comparator_factory: a class which extends
+ :class:`.CompositeProperty.Comparator` which provides custom SQL
+ clause generation for comparison operations.
+
+ :param doc:
+ optional string that will be applied as the doc on the
+ class-bound descriptor.
+
+ :param info: Optional data dictionary which will be populated into the
+ :attr:`.MapperProperty.info` attribute of this object.
+
+ """
+ return CompositeProperty(class_, *attrs, **kwargs)
+
+
+def with_loader_criteria(
+ entity_or_base,
+ where_criteria,
+ loader_only=False,
+ include_aliases=False,
+ propagate_to_loaders=True,
+ track_closure_variables=True,
+) -> "LoaderCriteriaOption":
+ """Add additional WHERE criteria to the load for all occurrences of
+ a particular entity.
+
+ .. versionadded:: 1.4
+
+ The :func:`_orm.with_loader_criteria` option is intended to add
+ limiting criteria to a particular kind of entity in a query,
+ **globally**, meaning it will apply to the entity as it appears
+ in the SELECT query as well as within any subqueries, join
+ conditions, and relationship loads, including both eager and lazy
+ loaders, without the need for it to be specified in any particular
+ part of the query. The rendering logic uses the same system used by
+ single table inheritance to ensure a certain discriminator is applied
+ to a table.
+
+ E.g., using :term:`2.0-style` queries, we can limit the way the
+ ``User.addresses`` collection is loaded, regardless of the kind
+ of loading used::
+
+ from sqlalchemy.orm import with_loader_criteria
+
+ stmt = select(User).options(
+ selectinload(User.addresses),
+ with_loader_criteria(Address, Address.email_address != 'foo'))
+ )
+
+ Above, the "selectinload" for ``User.addresses`` will apply the
+ given filtering criteria to the WHERE clause.
+
+ Another example, where the filtering will be applied to the
+ ON clause of the join, in this example using :term:`1.x style`
+ queries::
+
+ q = session.query(User).outerjoin(User.addresses).options(
+ with_loader_criteria(Address, Address.email_address != 'foo'))
+ )
+
+ The primary purpose of :func:`_orm.with_loader_criteria` is to use
+ it in the :meth:`_orm.SessionEvents.do_orm_execute` event handler
+ to ensure that all occurrences of a particular entity are filtered
+ in a certain way, such as filtering for access control roles. It
+ also can be used to apply criteria to relationship loads. In the
+ example below, we can apply a certain set of rules to all queries
+ emitted by a particular :class:`_orm.Session`::
+
+ session = Session(bind=engine)
+
+ @event.listens_for("do_orm_execute", session)
+ def _add_filtering_criteria(execute_state):
+
+ if (
+ execute_state.is_select
+ and not execute_state.is_column_load
+ and not execute_state.is_relationship_load
+ ):
+ execute_state.statement = execute_state.statement.options(
+ with_loader_criteria(
+ SecurityRole,
+ lambda cls: cls.role.in_(['some_role']),
+ include_aliases=True
+ )
+ )
+
+ In the above example, the :meth:`_orm.SessionEvents.do_orm_execute`
+ event will intercept all queries emitted using the
+ :class:`_orm.Session`. For those queries which are SELECT statements
+ and are not attribute or relationship loads a custom
+ :func:`_orm.with_loader_criteria` option is added to the query. The
+ :func:`_orm.with_loader_criteria` option will be used in the given
+ statement and will also be automatically propagated to all relationship
+ loads that descend from this query.
+
+ The criteria argument given is a ``lambda`` that accepts a ``cls``
+ argument. The given class will expand to include all mapped subclass
+ and need not itself be a mapped class.
+
+ .. tip::
+
+ When using :func:`_orm.with_loader_criteria` option in
+ conjunction with the :func:`_orm.contains_eager` loader option,
+ it's important to note that :func:`_orm.with_loader_criteria` only
+ affects the part of the query that determines what SQL is rendered
+ in terms of the WHERE and FROM clauses. The
+ :func:`_orm.contains_eager` option does not affect the rendering of
+ the SELECT statement outside of the columns clause, so does not have
+ any interaction with the :func:`_orm.with_loader_criteria` option.
+ However, the way things "work" is that :func:`_orm.contains_eager`
+ is meant to be used with a query that is already selecting from the
+ additional entities in some way, where
+ :func:`_orm.with_loader_criteria` can apply it's additional
+ criteria.
+
+ In the example below, assuming a mapping relationship as
+ ``A -> A.bs -> B``, the given :func:`_orm.with_loader_criteria`
+ option will affect the way in which the JOIN is rendered::
+
+ stmt = select(A).join(A.bs).options(
+ contains_eager(A.bs),
+ with_loader_criteria(B, B.flag == 1)
+ )
+
+ Above, the given :func:`_orm.with_loader_criteria` option will
+ affect the ON clause of the JOIN that is specified by
+ ``.join(A.bs)``, so is applied as expected. The
+ :func:`_orm.contains_eager` option has the effect that columns from
+ ``B`` are added to the columns clause::
+
+ SELECT
+ b.id, b.a_id, b.data, b.flag,
+ a.id AS id_1,
+ a.data AS data_1
+ FROM a JOIN b ON a.id = b.a_id AND b.flag = :flag_1
+
+
+ The use of the :func:`_orm.contains_eager` option within the above
+ statement has no effect on the behavior of the
+ :func:`_orm.with_loader_criteria` option. If the
+ :func:`_orm.contains_eager` option were omitted, the SQL would be
+ the same as regards the FROM and WHERE clauses, where
+ :func:`_orm.with_loader_criteria` continues to add its criteria to
+ the ON clause of the JOIN. The addition of
+ :func:`_orm.contains_eager` only affects the columns clause, in that
+ additional columns against ``b`` are added which are then consumed
+ by the ORM to produce ``B`` instances.
+
+ .. warning:: The use of a lambda inside of the call to
+ :func:`_orm.with_loader_criteria` is only invoked **once per unique
+ class**. Custom functions should not be invoked within this lambda.
+ See :ref:`engine_lambda_caching` for an overview of the "lambda SQL"
+ feature, which is for advanced use only.
+
+ :param entity_or_base: a mapped class, or a class that is a super
+ class of a particular set of mapped classes, to which the rule
+ will apply.
+
+ :param where_criteria: a Core SQL expression that applies limiting
+ criteria. This may also be a "lambda:" or Python function that
+ accepts a target class as an argument, when the given class is
+ a base with many different mapped subclasses.
+
+ :param include_aliases: if True, apply the rule to :func:`_orm.aliased`
+ constructs as well.
+
+ :param propagate_to_loaders: defaults to True, apply to relationship
+ loaders such as lazy loaders.
+
+
+ .. seealso::
+
+ :ref:`examples_session_orm_events` - includes examples of using
+ :func:`_orm.with_loader_criteria`.
+
+ :ref:`do_orm_execute_global_criteria` - basic example on how to
+ combine :func:`_orm.with_loader_criteria` with the
+ :meth:`_orm.SessionEvents.do_orm_execute` event.
+
+ :param track_closure_variables: when False, closure variables inside
+ of a lambda expression will not be used as part of
+ any cache key. This allows more complex expressions to be used
+ inside of a lambda expression but requires that the lambda ensures
+ it returns the identical SQL every time given a particular class.
+
+ .. versionadded:: 1.4.0b2
+
+ """
+ return LoaderCriteriaOption(
+ entity_or_base,
+ where_criteria,
+ loader_only,
+ include_aliases,
+ propagate_to_loaders,
+ track_closure_variables,
+ )
+
+
+def relationship(
+ argument: Union[str, Type[_RC], Callable[[], Type[_RC]]],
+ secondary=None,
+ primaryjoin=None,
+ secondaryjoin=None,
+ foreign_keys=None,
+ uselist=None,
+ order_by=False,
+ backref=None,
+ back_populates=None,
+ overlaps=None,
+ post_update=False,
+ cascade=False,
+ viewonly=False,
+ lazy="select",
+ collection_class=None,
+ passive_deletes=RelationshipProperty._persistence_only["passive_deletes"],
+ passive_updates=RelationshipProperty._persistence_only["passive_updates"],
+ remote_side=None,
+ enable_typechecks=RelationshipProperty._persistence_only[
+ "enable_typechecks"
+ ],
+ join_depth=None,
+ comparator_factory=None,
+ single_parent=False,
+ innerjoin=False,
+ distinct_target_key=None,
+ doc=None,
+ active_history=RelationshipProperty._persistence_only["active_history"],
+ cascade_backrefs=RelationshipProperty._persistence_only[
+ "cascade_backrefs"
+ ],
+ load_on_pending=False,
+ bake_queries=True,
+ _local_remote_pairs=None,
+ query_class=None,
+ info=None,
+ omit_join=None,
+ sync_backref=None,
+ _legacy_inactive_history_style=False,
+) -> RelationshipProperty[_RC]:
+ """Provide a relationship between two mapped classes.
+
+ This corresponds to a parent-child or associative table relationship.
+ The constructed class is an instance of
+ :class:`.RelationshipProperty`.
+
+ A typical :func:`_orm.relationship`, used in a classical mapping::
+
+ mapper(Parent, properties={
+ 'children': relationship(Child)
+ })
+
+ Some arguments accepted by :func:`_orm.relationship`
+ optionally accept a
+ callable function, which when called produces the desired value.
+ The callable is invoked by the parent :class:`_orm.Mapper` at "mapper
+ initialization" time, which happens only when mappers are first used,
+ and is assumed to be after all mappings have been constructed. This
+ can be used to resolve order-of-declaration and other dependency
+ issues, such as if ``Child`` is declared below ``Parent`` in the same
+ file::
+
+ mapper(Parent, properties={
+ "children":relationship(lambda: Child,
+ order_by=lambda: Child.id)
+ })
+
+ When using the :ref:`declarative_toplevel` extension, the Declarative
+ initializer allows string arguments to be passed to
+ :func:`_orm.relationship`. These string arguments are converted into
+ callables that evaluate the string as Python code, using the
+ Declarative class-registry as a namespace. This allows the lookup of
+ related classes to be automatic via their string name, and removes the
+ need for related classes to be imported into the local module space
+ before the dependent classes have been declared. It is still required
+ that the modules in which these related classes appear are imported
+ anywhere in the application at some point before the related mappings
+ are actually used, else a lookup error will be raised when the
+ :func:`_orm.relationship`
+ attempts to resolve the string reference to the
+ related class. An example of a string- resolved class is as
+ follows::
+
+ from sqlalchemy.ext.declarative import declarative_base
+
+ Base = declarative_base()
+
+ class Parent(Base):
+ __tablename__ = 'parent'
+ id = Column(Integer, primary_key=True)
+ children = relationship("Child", order_by="Child.id")
+
+ .. seealso::
+
+ :ref:`relationship_config_toplevel` - Full introductory and
+ reference documentation for :func:`_orm.relationship`.
+
+ :ref:`orm_tutorial_relationship` - ORM tutorial introduction.
+
+ :param argument:
+ A mapped class, or actual :class:`_orm.Mapper` instance,
+ representing
+ the target of the relationship.
+
+ :paramref:`_orm.relationship.argument`
+ may also be passed as a callable
+ function which is evaluated at mapper initialization time, and may
+ be passed as a string name when using Declarative.
+
+ .. warning:: Prior to SQLAlchemy 1.3.16, this value is interpreted
+ using Python's ``eval()`` function.
+ **DO NOT PASS UNTRUSTED INPUT TO THIS STRING**.
+ See :ref:`declarative_relationship_eval` for details on
+ declarative evaluation of :func:`_orm.relationship` arguments.
+
+ .. versionchanged 1.3.16::
+
+ The string evaluation of the main "argument" no longer accepts an
+ open ended Python expression, instead only accepting a string
+ class name or dotted package-qualified name.
+
+ .. seealso::
+
+ :ref:`declarative_configuring_relationships` - further detail
+ on relationship configuration when using Declarative.
+
+ :param secondary:
+ For a many-to-many relationship, specifies the intermediary
+ table, and is typically an instance of :class:`_schema.Table`.
+ In less common circumstances, the argument may also be specified
+ as an :class:`_expression.Alias` construct, or even a
+ :class:`_expression.Join` construct.
+
+ :paramref:`_orm.relationship.secondary` may
+ also be passed as a callable function which is evaluated at
+ mapper initialization time. When using Declarative, it may also
+ be a string argument noting the name of a :class:`_schema.Table`
+ that is
+ present in the :class:`_schema.MetaData`
+ collection associated with the
+ parent-mapped :class:`_schema.Table`.
+
+ .. warning:: When passed as a Python-evaluable string, the
+ argument is interpreted using Python's ``eval()`` function.
+ **DO NOT PASS UNTRUSTED INPUT TO THIS STRING**.
+ See :ref:`declarative_relationship_eval` for details on
+ declarative evaluation of :func:`_orm.relationship` arguments.
+
+ The :paramref:`_orm.relationship.secondary` keyword argument is
+ typically applied in the case where the intermediary
+ :class:`_schema.Table`
+ is not otherwise expressed in any direct class mapping. If the
+ "secondary" table is also explicitly mapped elsewhere (e.g. as in
+ :ref:`association_pattern`), one should consider applying the
+ :paramref:`_orm.relationship.viewonly` flag so that this
+ :func:`_orm.relationship`
+ is not used for persistence operations which
+ may conflict with those of the association object pattern.
+
+ .. seealso::
+
+ :ref:`relationships_many_to_many` - Reference example of "many
+ to many".
+
+ :ref:`orm_tutorial_many_to_many` - ORM tutorial introduction to
+ many-to-many relationships.
+
+ :ref:`self_referential_many_to_many` - Specifics on using
+ many-to-many in a self-referential case.
+
+ :ref:`declarative_many_to_many` - Additional options when using
+ Declarative.
+
+ :ref:`association_pattern` - an alternative to
+ :paramref:`_orm.relationship.secondary`
+ when composing association
+ table relationships, allowing additional attributes to be
+ specified on the association table.
+
+ :ref:`composite_secondary_join` - a lesser-used pattern which
+ in some cases can enable complex :func:`_orm.relationship` SQL
+ conditions to be used.
+
+ .. versionadded:: 0.9.2 :paramref:`_orm.relationship.secondary`
+ works
+ more effectively when referring to a :class:`_expression.Join`
+ instance.
+
+ :param active_history=False:
+ When ``True``, indicates that the "previous" value for a
+ many-to-one reference should be loaded when replaced, if
+ not already loaded. Normally, history tracking logic for
+ simple many-to-ones only needs to be aware of the "new"
+ value in order to perform a flush. This flag is available
+ for applications that make use of
+ :func:`.attributes.get_history` which also need to know
+ the "previous" value of the attribute.
+
+ :param backref:
+ Indicates the string name of a property to be placed on the related
+ mapper's class that will handle this relationship in the other
+ direction. The other property will be created automatically
+ when the mappers are configured. Can also be passed as a
+ :func:`.backref` object to control the configuration of the
+ new relationship.
+
+ .. seealso::
+
+ :ref:`relationships_backref` - Introductory documentation and
+ examples.
+
+ :paramref:`_orm.relationship.back_populates` - alternative form
+ of backref specification.
+
+ :func:`.backref` - allows control over :func:`_orm.relationship`
+ configuration when using :paramref:`_orm.relationship.backref`.
+
+
+ :param back_populates:
+ Takes a string name and has the same meaning as
+ :paramref:`_orm.relationship.backref`, except the complementing
+ property is **not** created automatically, and instead must be
+ configured explicitly on the other mapper. The complementing
+ property should also indicate
+ :paramref:`_orm.relationship.back_populates` to this relationship to
+ ensure proper functioning.
+
+ .. seealso::
+
+ :ref:`relationships_backref` - Introductory documentation and
+ examples.
+
+ :paramref:`_orm.relationship.backref` - alternative form
+ of backref specification.
+
+ :param overlaps:
+ A string name or comma-delimited set of names of other relationships
+ on either this mapper, a descendant mapper, or a target mapper with
+ which this relationship may write to the same foreign keys upon
+ persistence. The only effect this has is to eliminate the
+ warning that this relationship will conflict with another upon
+ persistence. This is used for such relationships that are truly
+ capable of conflicting with each other on write, but the application
+ will ensure that no such conflicts occur.
+
+ .. versionadded:: 1.4
+
+ .. seealso::
+
+ :ref:`error_qzyx` - usage example
+
+ :param bake_queries=True:
+ Enable :ref:`lambda caching <engine_lambda_caching>` for loader
+ strategies, if applicable, which adds a performance gain to the
+ construction of SQL constructs used by loader strategies, in addition
+ to the usual SQL statement caching used throughout SQLAlchemy. This
+ parameter currently applies only to the "lazy" and "selectin" loader
+ strategies. There is generally no reason to set this parameter to
+ False.
+
+ .. versionchanged:: 1.4 Relationship loaders no longer use the
+ previous "baked query" system of query caching. The "lazy"
+ and "selectin" loaders make use of the "lambda cache" system
+ for the construction of SQL constructs,
+ as well as the usual SQL caching system that is throughout
+ SQLAlchemy as of the 1.4 series.
+
+ :param cascade:
+ A comma-separated list of cascade rules which determines how
+ Session operations should be "cascaded" from parent to child.
+ This defaults to ``False``, which means the default cascade
+ should be used - this default cascade is ``"save-update, merge"``.
+
+ The available cascades are ``save-update``, ``merge``,
+ ``expunge``, ``delete``, ``delete-orphan``, and ``refresh-expire``.
+ An additional option, ``all`` indicates shorthand for
+ ``"save-update, merge, refresh-expire,
+ expunge, delete"``, and is often used as in ``"all, delete-orphan"``
+ to indicate that related objects should follow along with the
+ parent object in all cases, and be deleted when de-associated.
+
+ .. seealso::
+
+ :ref:`unitofwork_cascades` - Full detail on each of the available
+ cascade options.
+
+ :ref:`tutorial_delete_cascade` - Tutorial example describing
+ a delete cascade.
+
+ :param cascade_backrefs=False:
+ Legacy; this flag is always False.
+
+ .. versionchanged:: 2.0 "cascade_backrefs" functionality has been
+ removed.
+
+ :param collection_class:
+ A class or callable that returns a new list-holding object. will
+ be used in place of a plain list for storing elements.
+
+ .. seealso::
+
+ :ref:`custom_collections` - Introductory documentation and
+ examples.
+
+ :param comparator_factory:
+ A class which extends :class:`.RelationshipProperty.Comparator`
+ which provides custom SQL clause generation for comparison
+ operations.
+
+ .. seealso::
+
+ :class:`.PropComparator` - some detail on redefining comparators
+ at this level.
+
+ :ref:`custom_comparators` - Brief intro to this feature.
+
+
+ :param distinct_target_key=None:
+ Indicate if a "subquery" eager load should apply the DISTINCT
+ keyword to the innermost SELECT statement. When left as ``None``,
+ the DISTINCT keyword will be applied in those cases when the target
+ columns do not comprise the full primary key of the target table.
+ When set to ``True``, the DISTINCT keyword is applied to the
+ innermost SELECT unconditionally.
+
+ It may be desirable to set this flag to False when the DISTINCT is
+ reducing performance of the innermost subquery beyond that of what
+ duplicate innermost rows may be causing.
+
+ .. versionchanged:: 0.9.0 -
+ :paramref:`_orm.relationship.distinct_target_key` now defaults to
+ ``None``, so that the feature enables itself automatically for
+ those cases where the innermost query targets a non-unique
+ key.
+
+ .. seealso::
+
+ :ref:`loading_toplevel` - includes an introduction to subquery
+ eager loading.
+
+ :param doc:
+ Docstring which will be applied to the resulting descriptor.
+
+ :param foreign_keys:
+
+ A list of columns which are to be used as "foreign key"
+ columns, or columns which refer to the value in a remote
+ column, within the context of this :func:`_orm.relationship`
+ object's :paramref:`_orm.relationship.primaryjoin` condition.
+ That is, if the :paramref:`_orm.relationship.primaryjoin`
+ condition of this :func:`_orm.relationship` is ``a.id ==
+ b.a_id``, and the values in ``b.a_id`` are required to be
+ present in ``a.id``, then the "foreign key" column of this
+ :func:`_orm.relationship` is ``b.a_id``.
+
+ In normal cases, the :paramref:`_orm.relationship.foreign_keys`
+ parameter is **not required.** :func:`_orm.relationship` will
+ automatically determine which columns in the
+ :paramref:`_orm.relationship.primaryjoin` condition are to be
+ considered "foreign key" columns based on those
+ :class:`_schema.Column` objects that specify
+ :class:`_schema.ForeignKey`,
+ or are otherwise listed as referencing columns in a
+ :class:`_schema.ForeignKeyConstraint` construct.
+ :paramref:`_orm.relationship.foreign_keys` is only needed when:
+
+ 1. There is more than one way to construct a join from the local
+ table to the remote table, as there are multiple foreign key
+ references present. Setting ``foreign_keys`` will limit the
+ :func:`_orm.relationship`
+ to consider just those columns specified
+ here as "foreign".
+
+ 2. The :class:`_schema.Table` being mapped does not actually have
+ :class:`_schema.ForeignKey` or
+ :class:`_schema.ForeignKeyConstraint`
+ constructs present, often because the table
+ was reflected from a database that does not support foreign key
+ reflection (MySQL MyISAM).
+
+ 3. The :paramref:`_orm.relationship.primaryjoin`
+ argument is used to
+ construct a non-standard join condition, which makes use of
+ columns or expressions that do not normally refer to their
+ "parent" column, such as a join condition expressed by a
+ complex comparison using a SQL function.
+
+ The :func:`_orm.relationship` construct will raise informative
+ error messages that suggest the use of the
+ :paramref:`_orm.relationship.foreign_keys` parameter when
+ presented with an ambiguous condition. In typical cases,
+ if :func:`_orm.relationship` doesn't raise any exceptions, the
+ :paramref:`_orm.relationship.foreign_keys` parameter is usually
+ not needed.
+
+ :paramref:`_orm.relationship.foreign_keys` may also be passed as a
+ callable function which is evaluated at mapper initialization time,
+ and may be passed as a Python-evaluable string when using
+ Declarative.
+
+ .. warning:: When passed as a Python-evaluable string, the
+ argument is interpreted using Python's ``eval()`` function.
+ **DO NOT PASS UNTRUSTED INPUT TO THIS STRING**.
+ See :ref:`declarative_relationship_eval` for details on
+ declarative evaluation of :func:`_orm.relationship` arguments.
+
+ .. seealso::
+
+ :ref:`relationship_foreign_keys`
+
+ :ref:`relationship_custom_foreign`
+
+ :func:`.foreign` - allows direct annotation of the "foreign"
+ columns within a :paramref:`_orm.relationship.primaryjoin`
+ condition.
+
+ :param info: Optional data dictionary which will be populated into the
+ :attr:`.MapperProperty.info` attribute of this object.
+
+ :param innerjoin=False:
+ When ``True``, joined eager loads will use an inner join to join
+ against related tables instead of an outer join. The purpose
+ of this option is generally one of performance, as inner joins
+ generally perform better than outer joins.
+
+ This flag can be set to ``True`` when the relationship references an
+ object via many-to-one using local foreign keys that are not
+ nullable, or when the reference is one-to-one or a collection that
+ is guaranteed to have one or at least one entry.
+
+ The option supports the same "nested" and "unnested" options as
+ that of :paramref:`_orm.joinedload.innerjoin`. See that flag
+ for details on nested / unnested behaviors.
+
+ .. seealso::
+
+ :paramref:`_orm.joinedload.innerjoin` - the option as specified by
+ loader option, including detail on nesting behavior.
+
+ :ref:`what_kind_of_loading` - Discussion of some details of
+ various loader options.
+
+
+ :param join_depth:
+ When non-``None``, an integer value indicating how many levels
+ deep "eager" loaders should join on a self-referring or cyclical
+ relationship. The number counts how many times the same Mapper
+ shall be present in the loading condition along a particular join
+ branch. When left at its default of ``None``, eager loaders
+ will stop chaining when they encounter a the same target mapper
+ which is already higher up in the chain. This option applies
+ both to joined- and subquery- eager loaders.
+
+ .. seealso::
+
+ :ref:`self_referential_eager_loading` - Introductory documentation
+ and examples.
+
+ :param lazy='select': specifies
+ How the related items should be loaded. Default value is
+ ``select``. Values include:
+
+ * ``select`` - items should be loaded lazily when the property is
+ first accessed, using a separate SELECT statement, or identity map
+ fetch for simple many-to-one references.
+
+ * ``immediate`` - items should be loaded as the parents are loaded,
+ using a separate SELECT statement, or identity map fetch for
+ simple many-to-one references.
+
+ * ``joined`` - items should be loaded "eagerly" in the same query as
+ that of the parent, using a JOIN or LEFT OUTER JOIN. Whether
+ the join is "outer" or not is determined by the
+ :paramref:`_orm.relationship.innerjoin` parameter.
+
+ * ``subquery`` - items should be loaded "eagerly" as the parents are
+ loaded, using one additional SQL statement, which issues a JOIN to
+ a subquery of the original statement, for each collection
+ requested.
+
+ * ``selectin`` - items should be loaded "eagerly" as the parents
+ are loaded, using one or more additional SQL statements, which
+ issues a JOIN to the immediate parent object, specifying primary
+ key identifiers using an IN clause.
+
+ .. versionadded:: 1.2
+
+ * ``noload`` - no loading should occur at any time. This is to
+ support "write-only" attributes, or attributes which are
+ populated in some manner specific to the application.
+
+ * ``raise`` - lazy loading is disallowed; accessing
+ the attribute, if its value were not already loaded via eager
+ loading, will raise an :exc:`~sqlalchemy.exc.InvalidRequestError`.
+ This strategy can be used when objects are to be detached from
+ their attached :class:`.Session` after they are loaded.
+
+ .. versionadded:: 1.1
+
+ * ``raise_on_sql`` - lazy loading that emits SQL is disallowed;
+ accessing the attribute, if its value were not already loaded via
+ eager loading, will raise an
+ :exc:`~sqlalchemy.exc.InvalidRequestError`, **if the lazy load
+ needs to emit SQL**. If the lazy load can pull the related value
+ from the identity map or determine that it should be None, the
+ value is loaded. This strategy can be used when objects will
+ remain associated with the attached :class:`.Session`, however
+ additional SELECT statements should be blocked.
+
+ .. versionadded:: 1.1
+
+ * ``dynamic`` - the attribute will return a pre-configured
+ :class:`_query.Query` object for all read
+ operations, onto which further filtering operations can be
+ applied before iterating the results. See
+ the section :ref:`dynamic_relationship` for more details.
+
+ * True - a synonym for 'select'
+
+ * False - a synonym for 'joined'
+
+ * None - a synonym for 'noload'
+
+ .. seealso::
+
+ :doc:`/orm/loading_relationships` - Full documentation on
+ relationship loader configuration.
+
+ :ref:`dynamic_relationship` - detail on the ``dynamic`` option.
+
+ :ref:`collections_noload_raiseload` - notes on "noload" and "raise"
+
+ :param load_on_pending=False:
+ Indicates loading behavior for transient or pending parent objects.
+
+ When set to ``True``, causes the lazy-loader to
+ issue a query for a parent object that is not persistent, meaning it
+ has never been flushed. This may take effect for a pending object
+ when autoflush is disabled, or for a transient object that has been
+ "attached" to a :class:`.Session` but is not part of its pending
+ collection.
+
+ The :paramref:`_orm.relationship.load_on_pending`
+ flag does not improve
+ behavior when the ORM is used normally - object references should be
+ constructed at the object level, not at the foreign key level, so
+ that they are present in an ordinary way before a flush proceeds.
+ This flag is not not intended for general use.
+
+ .. seealso::
+
+ :meth:`.Session.enable_relationship_loading` - this method
+ establishes "load on pending" behavior for the whole object, and
+ also allows loading on objects that remain transient or
+ detached.
+
+ :param order_by:
+ Indicates the ordering that should be applied when loading these
+ items. :paramref:`_orm.relationship.order_by`
+ is expected to refer to
+ one of the :class:`_schema.Column`
+ objects to which the target class is
+ mapped, or the attribute itself bound to the target class which
+ refers to the column.
+
+ :paramref:`_orm.relationship.order_by`
+ may also be passed as a callable
+ function which is evaluated at mapper initialization time, and may
+ be passed as a Python-evaluable string when using Declarative.
+
+ .. warning:: When passed as a Python-evaluable string, the
+ argument is interpreted using Python's ``eval()`` function.
+ **DO NOT PASS UNTRUSTED INPUT TO THIS STRING**.
+ See :ref:`declarative_relationship_eval` for details on
+ declarative evaluation of :func:`_orm.relationship` arguments.
+
+ :param passive_deletes=False:
+ Indicates loading behavior during delete operations.
+
+ A value of True indicates that unloaded child items should not
+ be loaded during a delete operation on the parent. Normally,
+ when a parent item is deleted, all child items are loaded so
+ that they can either be marked as deleted, or have their
+ foreign key to the parent set to NULL. Marking this flag as
+ True usually implies an ON DELETE <CASCADE|SET NULL> rule is in
+ place which will handle updating/deleting child rows on the
+ database side.
+
+ Additionally, setting the flag to the string value 'all' will
+ disable the "nulling out" of the child foreign keys, when the parent
+ object is deleted and there is no delete or delete-orphan cascade
+ enabled. This is typically used when a triggering or error raise
+ scenario is in place on the database side. Note that the foreign
+ key attributes on in-session child objects will not be changed after
+ a flush occurs so this is a very special use-case setting.
+ Additionally, the "nulling out" will still occur if the child
+ object is de-associated with the parent.
+
+ .. seealso::
+
+ :ref:`passive_deletes` - Introductory documentation
+ and examples.
+
+ :param passive_updates=True:
+ Indicates the persistence behavior to take when a referenced
+ primary key value changes in place, indicating that the referencing
+ foreign key columns will also need their value changed.
+
+ When True, it is assumed that ``ON UPDATE CASCADE`` is configured on
+ the foreign key in the database, and that the database will
+ handle propagation of an UPDATE from a source column to
+ dependent rows. When False, the SQLAlchemy
+ :func:`_orm.relationship`
+ construct will attempt to emit its own UPDATE statements to
+ modify related targets. However note that SQLAlchemy **cannot**
+ emit an UPDATE for more than one level of cascade. Also,
+ setting this flag to False is not compatible in the case where
+ the database is in fact enforcing referential integrity, unless
+ those constraints are explicitly "deferred", if the target backend
+ supports it.
+
+ It is highly advised that an application which is employing
+ mutable primary keys keeps ``passive_updates`` set to True,
+ and instead uses the referential integrity features of the database
+ itself in order to handle the change efficiently and fully.
+
+ .. seealso::
+
+ :ref:`passive_updates` - Introductory documentation and
+ examples.
+
+ :paramref:`.mapper.passive_updates` - a similar flag which
+ takes effect for joined-table inheritance mappings.
+
+ :param post_update:
+ This indicates that the relationship should be handled by a
+ second UPDATE statement after an INSERT or before a
+ DELETE. Currently, it also will issue an UPDATE after the
+ instance was UPDATEd as well, although this technically should
+ be improved. This flag is used to handle saving bi-directional
+ dependencies between two individual rows (i.e. each row
+ references the other), where it would otherwise be impossible to
+ INSERT or DELETE both rows fully since one row exists before the
+ other. Use this flag when a particular mapping arrangement will
+ incur two rows that are dependent on each other, such as a table
+ that has a one-to-many relationship to a set of child rows, and
+ also has a column that references a single child row within that
+ list (i.e. both tables contain a foreign key to each other). If
+ a flush operation returns an error that a "cyclical
+ dependency" was detected, this is a cue that you might want to
+ use :paramref:`_orm.relationship.post_update` to "break" the cycle.
+
+ .. seealso::
+
+ :ref:`post_update` - Introductory documentation and examples.
+
+ :param primaryjoin:
+ A SQL expression that will be used as the primary
+ join of the child object against the parent object, or in a
+ many-to-many relationship the join of the parent object to the
+ association table. By default, this value is computed based on the
+ foreign key relationships of the parent and child tables (or
+ association table).
+
+ :paramref:`_orm.relationship.primaryjoin` may also be passed as a
+ callable function which is evaluated at mapper initialization time,
+ and may be passed as a Python-evaluable string when using
+ Declarative.
+
+ .. warning:: When passed as a Python-evaluable string, the
+ argument is interpreted using Python's ``eval()`` function.
+ **DO NOT PASS UNTRUSTED INPUT TO THIS STRING**.
+ See :ref:`declarative_relationship_eval` for details on
+ declarative evaluation of :func:`_orm.relationship` arguments.
+
+ .. seealso::
+
+ :ref:`relationship_primaryjoin`
+
+ :param remote_side:
+ Used for self-referential relationships, indicates the column or
+ list of columns that form the "remote side" of the relationship.
+
+ :paramref:`_orm.relationship.remote_side` may also be passed as a
+ callable function which is evaluated at mapper initialization time,
+ and may be passed as a Python-evaluable string when using
+ Declarative.
+
+ .. warning:: When passed as a Python-evaluable string, the
+ argument is interpreted using Python's ``eval()`` function.
+ **DO NOT PASS UNTRUSTED INPUT TO THIS STRING**.
+ See :ref:`declarative_relationship_eval` for details on
+ declarative evaluation of :func:`_orm.relationship` arguments.
+
+ .. seealso::
+
+ :ref:`self_referential` - in-depth explanation of how
+ :paramref:`_orm.relationship.remote_side`
+ is used to configure self-referential relationships.
+
+ :func:`.remote` - an annotation function that accomplishes the
+ same purpose as :paramref:`_orm.relationship.remote_side`,
+ typically
+ when a custom :paramref:`_orm.relationship.primaryjoin` condition
+ is used.
+
+ :param query_class:
+ A :class:`_query.Query`
+ subclass that will be used internally by the
+ ``AppenderQuery`` returned by a "dynamic" relationship, that
+ is, a relationship that specifies ``lazy="dynamic"`` or was
+ otherwise constructed using the :func:`_orm.dynamic_loader`
+ function.
+
+ .. seealso::
+
+ :ref:`dynamic_relationship` - Introduction to "dynamic"
+ relationship loaders.
+
+ :param secondaryjoin:
+ A SQL expression that will be used as the join of
+ an association table to the child object. By default, this value is
+ computed based on the foreign key relationships of the association
+ and child tables.
+
+ :paramref:`_orm.relationship.secondaryjoin` may also be passed as a
+ callable function which is evaluated at mapper initialization time,
+ and may be passed as a Python-evaluable string when using
+ Declarative.
+
+ .. warning:: When passed as a Python-evaluable string, the
+ argument is interpreted using Python's ``eval()`` function.
+ **DO NOT PASS UNTRUSTED INPUT TO THIS STRING**.
+ See :ref:`declarative_relationship_eval` for details on
+ declarative evaluation of :func:`_orm.relationship` arguments.
+
+ .. seealso::
+
+ :ref:`relationship_primaryjoin`
+
+ :param single_parent:
+ When True, installs a validator which will prevent objects
+ from being associated with more than one parent at a time.
+ This is used for many-to-one or many-to-many relationships that
+ should be treated either as one-to-one or one-to-many. Its usage
+ is optional, except for :func:`_orm.relationship` constructs which
+ are many-to-one or many-to-many and also
+ specify the ``delete-orphan`` cascade option. The
+ :func:`_orm.relationship` construct itself will raise an error
+ instructing when this option is required.
+
+ .. seealso::
+
+ :ref:`unitofwork_cascades` - includes detail on when the
+ :paramref:`_orm.relationship.single_parent`
+ flag may be appropriate.
+
+ :param uselist:
+ A boolean that indicates if this property should be loaded as a
+ list or a scalar. In most cases, this value is determined
+ automatically by :func:`_orm.relationship` at mapper configuration
+ time, based on the type and direction
+ of the relationship - one to many forms a list, many to one
+ forms a scalar, many to many is a list. If a scalar is desired
+ where normally a list would be present, such as a bi-directional
+ one-to-one relationship, set :paramref:`_orm.relationship.uselist`
+ to
+ False.
+
+ The :paramref:`_orm.relationship.uselist`
+ flag is also available on an
+ existing :func:`_orm.relationship`
+ construct as a read-only attribute,
+ which can be used to determine if this :func:`_orm.relationship`
+ deals
+ with collections or scalar attributes::
+
+ >>> User.addresses.property.uselist
+ True
+
+ .. seealso::
+
+ :ref:`relationships_one_to_one` - Introduction to the "one to
+ one" relationship pattern, which is typically when the
+ :paramref:`_orm.relationship.uselist` flag is needed.
+
+ :param viewonly=False:
+ When set to ``True``, the relationship is used only for loading
+ objects, and not for any persistence operation. A
+ :func:`_orm.relationship` which specifies
+ :paramref:`_orm.relationship.viewonly` can work
+ with a wider range of SQL operations within the
+ :paramref:`_orm.relationship.primaryjoin` condition, including
+ operations that feature the use of a variety of comparison operators
+ as well as SQL functions such as :func:`_expression.cast`. The
+ :paramref:`_orm.relationship.viewonly`
+ flag is also of general use when defining any kind of
+ :func:`_orm.relationship` that doesn't represent
+ the full set of related objects, to prevent modifications of the
+ collection from resulting in persistence operations.
+
+ When using the :paramref:`_orm.relationship.viewonly` flag in
+ conjunction with backrefs, the originating relationship for a
+ particular state change will not produce state changes within the
+ viewonly relationship. This is the behavior implied by
+ :paramref:`_orm.relationship.sync_backref` being set to False.
+
+ .. versionchanged:: 1.3.17 - the
+ :paramref:`_orm.relationship.sync_backref` flag is set to False
+ when using viewonly in conjunction with backrefs.
+
+ .. seealso::
+
+ :paramref:`_orm.relationship.sync_backref`
+
+ :param sync_backref:
+ A boolean that enables the events used to synchronize the in-Python
+ attributes when this relationship is target of either
+ :paramref:`_orm.relationship.backref` or
+ :paramref:`_orm.relationship.back_populates`.
+
+ Defaults to ``None``, which indicates that an automatic value should
+ be selected based on the value of the
+ :paramref:`_orm.relationship.viewonly` flag. When left at its
+ default, changes in state will be back-populated only if neither
+ sides of a relationship is viewonly.
+
+ .. versionadded:: 1.3.17
+
+ .. versionchanged:: 1.4 - A relationship that specifies
+ :paramref:`_orm.relationship.viewonly` automatically implies
+ that :paramref:`_orm.relationship.sync_backref` is ``False``.
+
+ .. seealso::
+
+ :paramref:`_orm.relationship.viewonly`
+
+ :param omit_join:
+ Allows manual control over the "selectin" automatic join
+ optimization. Set to ``False`` to disable the "omit join" feature
+ added in SQLAlchemy 1.3; or leave as ``None`` to leave automatic
+ optimization in place.
+
+ .. note:: This flag may only be set to ``False``. It is not
+ necessary to set it to ``True`` as the "omit_join" optimization is
+ automatically detected; if it is not detected, then the
+ optimization is not supported.
+
+ .. versionchanged:: 1.3.11 setting ``omit_join`` to True will now
+ emit a warning as this was not the intended use of this flag.
+
+ .. versionadded:: 1.3
+
+
+ """
+ return RelationshipProperty(
+ argument,
+ secondary,
+ primaryjoin,
+ secondaryjoin,
+ foreign_keys,
+ uselist,
+ order_by,
+ backref,
+ back_populates,
+ overlaps,
+ post_update,
+ cascade,
+ viewonly,
+ lazy,
+ collection_class,
+ passive_deletes,
+ passive_updates,
+ remote_side,
+ enable_typechecks,
+ join_depth,
+ comparator_factory,
+ single_parent,
+ innerjoin,
+ distinct_target_key,
+ doc,
+ active_history,
+ cascade_backrefs,
+ load_on_pending,
+ bake_queries,
+ _local_remote_pairs,
+ query_class,
+ info,
+ omit_join,
+ sync_backref,
+ _legacy_inactive_history_style,
+ )
+
+
+def synonym(
+ name,
+ map_column=None,
+ descriptor=None,
+ comparator_factory=None,
+ doc=None,
+ info=None,
+) -> "SynonymProperty":
+ """Denote an attribute name as a synonym to a mapped property,
+ in that the attribute will mirror the value and expression behavior
+ of another attribute.
+
+ e.g.::
+
+ class MyClass(Base):
+ __tablename__ = 'my_table'
+
+ id = Column(Integer, primary_key=True)
+ job_status = Column(String(50))
+
+ status = synonym("job_status")
+
+
+ :param name: the name of the existing mapped property. This
+ can refer to the string name ORM-mapped attribute
+ configured on the class, including column-bound attributes
+ and relationships.
+
+ :param descriptor: a Python :term:`descriptor` that will be used
+ as a getter (and potentially a setter) when this attribute is
+ accessed at the instance level.
+
+ :param map_column: **For classical mappings and mappings against
+ an existing Table object only**. if ``True``, the :func:`.synonym`
+ construct will locate the :class:`_schema.Column`
+ object upon the mapped
+ table that would normally be associated with the attribute name of
+ this synonym, and produce a new :class:`.ColumnProperty` that instead
+ maps this :class:`_schema.Column`
+ to the alternate name given as the "name"
+ argument of the synonym; in this way, the usual step of redefining
+ the mapping of the :class:`_schema.Column`
+ to be under a different name is
+ unnecessary. This is usually intended to be used when a
+ :class:`_schema.Column`
+ is to be replaced with an attribute that also uses a
+ descriptor, that is, in conjunction with the
+ :paramref:`.synonym.descriptor` parameter::
+
+ my_table = Table(
+ "my_table", metadata,
+ Column('id', Integer, primary_key=True),
+ Column('job_status', String(50))
+ )
+
+ class MyClass:
+ @property
+ def _job_status_descriptor(self):
+ return "Status: %s" % self._job_status
+
+
+ mapper(
+ MyClass, my_table, properties={
+ "job_status": synonym(
+ "_job_status", map_column=True,
+ descriptor=MyClass._job_status_descriptor)
+ }
+ )
+
+ Above, the attribute named ``_job_status`` is automatically
+ mapped to the ``job_status`` column::
+
+ >>> j1 = MyClass()
+ >>> j1._job_status = "employed"
+ >>> j1.job_status
+ Status: employed
+
+ When using Declarative, in order to provide a descriptor in
+ conjunction with a synonym, use the
+ :func:`sqlalchemy.ext.declarative.synonym_for` helper. However,
+ note that the :ref:`hybrid properties <mapper_hybrids>` feature
+ should usually be preferred, particularly when redefining attribute
+ behavior.
+
+ :param info: Optional data dictionary which will be populated into the
+ :attr:`.InspectionAttr.info` attribute of this object.
+
+ .. versionadded:: 1.0.0
+
+ :param comparator_factory: A subclass of :class:`.PropComparator`
+ that will provide custom comparison behavior at the SQL expression
+ level.
+
+ .. note::
+
+ For the use case of providing an attribute which redefines both
+ Python-level and SQL-expression level behavior of an attribute,
+ please refer to the Hybrid attribute introduced at
+ :ref:`mapper_hybrids` for a more effective technique.
+
+ .. seealso::
+
+ :ref:`synonyms` - Overview of synonyms
+
+ :func:`.synonym_for` - a helper oriented towards Declarative
+
+ :ref:`mapper_hybrids` - The Hybrid Attribute extension provides an
+ updated approach to augmenting attribute behavior more flexibly
+ than can be achieved with synonyms.
+
+ """
+ return SynonymProperty(
+ name, map_column, descriptor, comparator_factory, doc, info
+ )
+
+
+def create_session(bind=None, **kwargs):
+ r"""Create a new :class:`.Session`
+ with no automation enabled by default.
+
+ This function is used primarily for testing. The usual
+ route to :class:`.Session` creation is via its constructor
+ or the :func:`.sessionmaker` function.
+
+ :param bind: optional, a single Connectable to use for all
+ database access in the created
+ :class:`~sqlalchemy.orm.session.Session`.
+
+ :param \*\*kwargs: optional, passed through to the
+ :class:`.Session` constructor.
+
+ :returns: an :class:`~sqlalchemy.orm.session.Session` instance
+
+ The defaults of create_session() are the opposite of that of
+ :func:`sessionmaker`; ``autoflush`` and ``expire_on_commit`` are
+ False.
+
+ Usage::
+
+ >>> from sqlalchemy.orm import create_session
+ >>> session = create_session()
+
+ It is recommended to use :func:`sessionmaker` instead of
+ create_session().
+
+ """
+
+ kwargs.setdefault("autoflush", False)
+ kwargs.setdefault("expire_on_commit", False)
+ return Session(bind=bind, **kwargs)
+
+
+def _mapper_fn(*arg, **kw):
+ """Placeholder for the now-removed ``mapper()`` function.
+
+ Classical mappings should be performed using the
+ :meth:`_orm.registry.map_imperatively` method.
+
+ This symbol remains in SQLAlchemy 2.0 to suit the deprecated use case
+ of using the ``mapper()`` function as a target for ORM event listeners,
+ which failed to be marked as deprecated in the 1.4 series.
+
+ Global ORM mapper listeners should instead use the :class:`_orm.Mapper`
+ class as the target.
+
+ .. versionchanged:: 2.0 The ``mapper()`` function was removed; the
+ symbol remains temporarily as a placeholder for the event listening
+ use case.
+
+ """
+ raise InvalidRequestError(
+ "The 'sqlalchemy.orm.mapper()' function is removed as of "
+ "SQLAlchemy 2.0. Use the "
+ "'sqlalchemy.orm.registry.map_imperatively()` "
+ "method of the ``sqlalchemy.orm.registry`` class to perform "
+ "classical mapping."
+ )
+
+
+def dynamic_loader(argument, **kw):
+ """Construct a dynamically-loading mapper property.
+
+ This is essentially the same as
+ using the ``lazy='dynamic'`` argument with :func:`relationship`::
+
+ dynamic_loader(SomeClass)
+
+ # is the same as
+
+ relationship(SomeClass, lazy="dynamic")
+
+ See the section :ref:`dynamic_relationship` for more details
+ on dynamic loading.
+
+ """
+ kw["lazy"] = "dynamic"
+ return relationship(argument, **kw)
+
+
+def backref(name, **kwargs):
+ """Create a back reference with explicit keyword arguments, which are the
+ same arguments one can send to :func:`relationship`.
+
+ Used with the ``backref`` keyword argument to :func:`relationship` in
+ place of a string argument, e.g.::
+
+ 'items':relationship(
+ SomeItem, backref=backref('parent', lazy='subquery'))
+
+ .. seealso::
+
+ :ref:`relationships_backref`
+
+ """
+
+ return (name, kwargs)
+
+
+def deferred(*columns, **kw):
+ r"""Indicate a column-based mapped attribute that by default will
+ not load unless accessed.
+
+ :param \*columns: columns to be mapped. This is typically a single
+ :class:`_schema.Column` object,
+ however a collection is supported in order
+ to support multiple columns mapped under the same attribute.
+
+ :param raiseload: boolean, if True, indicates an exception should be raised
+ if the load operation is to take place.
+
+ .. versionadded:: 1.4
+
+ .. seealso::
+
+ :ref:`deferred_raiseload`
+
+ :param \**kw: additional keyword arguments passed to
+ :class:`.ColumnProperty`.
+
+ .. seealso::
+
+ :ref:`deferred`
+
+ """
+ return ColumnProperty(deferred=True, *columns, **kw)
+
+
+def query_expression(default_expr=sql.null()):
+ """Indicate an attribute that populates from a query-time SQL expression.
+
+ :param default_expr: Optional SQL expression object that will be used in
+ all cases if not assigned later with :func:`_orm.with_expression`.
+ E.g.::
+
+ from sqlalchemy.sql import literal
+
+ class C(Base):
+ #...
+ my_expr = query_expression(literal(1))
+
+ .. versionadded:: 1.3.18
+
+
+ .. versionadded:: 1.2
+
+ .. seealso::
+
+ :ref:`mapper_querytime_expression`
+
+ """
+ prop = ColumnProperty(default_expr)
+ prop.strategy_key = (("query_expression", True),)
+ return prop
+
+
+def clear_mappers():
+ """Remove all mappers from all classes.
+
+ .. versionchanged:: 1.4 This function now locates all
+ :class:`_orm.registry` objects and calls upon the
+ :meth:`_orm.registry.dispose` method of each.
+
+ This function removes all instrumentation from classes and disposes
+ of their associated mappers. Once called, the classes are unmapped
+ and can be later re-mapped with new mappers.
+
+ :func:`.clear_mappers` is *not* for normal use, as there is literally no
+ valid usage for it outside of very specific testing scenarios. Normally,
+ mappers are permanent structural components of user-defined classes, and
+ are never discarded independently of their class. If a mapped class
+ itself is garbage collected, its mapper is automatically disposed of as
+ well. As such, :func:`.clear_mappers` is only for usage in test suites
+ that re-use the same classes with different mappings, which is itself an
+ extremely rare use case - the only such use case is in fact SQLAlchemy's
+ own test suite, and possibly the test suites of other ORM extension
+ libraries which intend to test various combinations of mapper construction
+ upon a fixed set of classes.
+
+ """
+
+ mapperlib._dispose_registries(mapperlib._all_registries(), False)
import operator
import typing
+from typing import Any
+from typing import Generic
+from typing import TypeVar
from . import exc
from .. import exc as sa_exc
from ..util import typing as compat_typing
+_T = TypeVar("_T", bound=Any)
+
PASSIVE_NO_RESULT = util.symbol(
"PASSIVE_NO_RESULT",
"""Symbol returned by a loader callable or other attribute/history
return {}
-class _MappedAttribute:
+class _MappedAttribute(Generic[_T]):
"""Mixin for attributes which should be replaced by mapper-assigned
attributes.
from ..sql.selectable import LABEL_STYLE_DISAMBIGUATE_ONLY
from ..sql.selectable import LABEL_STYLE_NONE
from ..sql.selectable import LABEL_STYLE_TABLENAME_PLUS_COL
+from ..sql.selectable import Select
from ..sql.selectable import SelectState
from ..sql.visitors import InternalTraversal
group_by,
):
- Select = future.Select
statement = Select._create_raw_select(
_raw_columns=raw_columns,
_from_obj=from_obj,
from . import exc as orm_exc
from . import instrumentation
from . import interfaces
-from . import mapper as mapperlib
+from . import mapperlib
from .base import _inspect_mapped_class
from .decl_base import _add_attribute
from .decl_base import _as_declarative
from sqlalchemy.orm import instrumentation
from . import clsregistry
from . import exc as orm_exc
-from . import mapper as mapperlib
+from . import mapperlib
from .attributes import InstrumentedAttribute
from .attributes import QueryableAttribute
from .base import _is_mapped_class
as actively in the load/persist ORM loop.
"""
+from typing import Any
+from typing import Type
+from typing import TypeVar
from . import attributes
from . import util as orm_util
from ..sql import expression
from ..sql import operators
+_T = TypeVar("_T", bound=Any)
-class DescriptorProperty(MapperProperty):
+
+class DescriptorProperty(MapperProperty[_T]):
""":class:`.MapperProperty` which proxies access to a
user-defined descriptor."""
mapper.class_manager.instrument_attribute(self.key, proxy_attr)
-class CompositeProperty(DescriptorProperty):
+class CompositeProperty(DescriptorProperty[_T]):
"""Defines a "composite" mapped attribute, representing a collection
of columns as one attribute.
"""
- def __init__(self, class_, *attrs, **kwargs):
- r"""Return a composite column-based property for use with a Mapper.
-
- See the mapping documentation section :ref:`mapper_composite` for a
- full usage example.
-
- The :class:`.MapperProperty` returned by :func:`.composite`
- is the :class:`.CompositeProperty`.
-
- :param class\_:
- The "composite type" class, or any classmethod or callable which
- will produce a new instance of the composite object given the
- column values in order.
-
- :param \*cols:
- List of Column objects to be mapped.
-
- :param active_history=False:
- When ``True``, indicates that the "previous" value for a
- scalar attribute should be loaded when replaced, if not
- already loaded. See the same flag on :func:`.column_property`.
-
- :param group:
- A group name for this property when marked as deferred.
-
- :param deferred:
- When True, the column property is "deferred", meaning that it does
- not load immediately, and is instead loaded when the attribute is
- first accessed on an instance. See also
- :func:`~sqlalchemy.orm.deferred`.
-
- :param comparator_factory: a class which extends
- :class:`.CompositeProperty.Comparator` which provides custom SQL
- clause generation for comparison operations.
-
- :param doc:
- optional string that will be applied as the doc on the
- class-bound descriptor.
-
- :param info: Optional data dictionary which will be populated into the
- :attr:`.MapperProperty.info` attribute of this object.
-
- """
+ def __init__(self, class_: Type[_T], *attrs, **kwargs):
super(CompositeProperty, self).__init__()
self.attrs = attrs
doc=None,
info=None,
):
- """Denote an attribute name as a synonym to a mapped property,
- in that the attribute will mirror the value and expression behavior
- of another attribute.
-
- e.g.::
-
- class MyClass(Base):
- __tablename__ = 'my_table'
-
- id = Column(Integer, primary_key=True)
- job_status = Column(String(50))
-
- status = synonym("job_status")
-
-
- :param name: the name of the existing mapped property. This
- can refer to the string name ORM-mapped attribute
- configured on the class, including column-bound attributes
- and relationships.
-
- :param descriptor: a Python :term:`descriptor` that will be used
- as a getter (and potentially a setter) when this attribute is
- accessed at the instance level.
-
- :param map_column: **For classical mappings and mappings against
- an existing Table object only**. if ``True``, the :func:`.synonym`
- construct will locate the :class:`_schema.Column`
- object upon the mapped
- table that would normally be associated with the attribute name of
- this synonym, and produce a new :class:`.ColumnProperty` that instead
- maps this :class:`_schema.Column`
- to the alternate name given as the "name"
- argument of the synonym; in this way, the usual step of redefining
- the mapping of the :class:`_schema.Column`
- to be under a different name is
- unnecessary. This is usually intended to be used when a
- :class:`_schema.Column`
- is to be replaced with an attribute that also uses a
- descriptor, that is, in conjunction with the
- :paramref:`.synonym.descriptor` parameter::
-
- my_table = Table(
- "my_table", metadata,
- Column('id', Integer, primary_key=True),
- Column('job_status', String(50))
- )
-
- class MyClass:
- @property
- def _job_status_descriptor(self):
- return "Status: %s" % self._job_status
-
-
- mapper(
- MyClass, my_table, properties={
- "job_status": synonym(
- "_job_status", map_column=True,
- descriptor=MyClass._job_status_descriptor)
- }
- )
-
- Above, the attribute named ``_job_status`` is automatically
- mapped to the ``job_status`` column::
-
- >>> j1 = MyClass()
- >>> j1._job_status = "employed"
- >>> j1.job_status
- Status: employed
-
- When using Declarative, in order to provide a descriptor in
- conjunction with a synonym, use the
- :func:`sqlalchemy.ext.declarative.synonym_for` helper. However,
- note that the :ref:`hybrid properties <mapper_hybrids>` feature
- should usually be preferred, particularly when redefining attribute
- behavior.
-
- :param info: Optional data dictionary which will be populated into the
- :attr:`.InspectionAttr.info` attribute of this object.
-
- .. versionadded:: 1.0.0
-
- :param comparator_factory: A subclass of :class:`.PropComparator`
- that will provide custom comparison behavior at the SQL expression
- level.
-
- .. note::
-
- For the use case of providing an attribute which redefines both
- Python-level and SQL-expression level behavior of an attribute,
- please refer to the Hybrid attribute introduced at
- :ref:`mapper_hybrids` for a more effective technique.
-
- .. seealso::
-
- :ref:`synonyms` - Overview of synonyms
-
- :func:`.synonym_for` - a helper oriented towards Declarative
-
- :ref:`mapper_hybrids` - The Hybrid Attribute extension provides an
- updated approach to augmenting attribute behavior more flexibly
- than can be achieved with synonyms.
-
- """
super(SynonymProperty, self).__init__()
self.name = name
from . import attributes
from . import exc as orm_exc
from . import interfaces
-from . import object_mapper
-from . import object_session
from . import relationships
from . import strategies
from . import util as orm_util
+from .base import object_mapper
from .query import Query
+from .session import object_session
from .. import exc
from .. import log
from .. import util
"""
import collections
+from typing import Any
+from typing import TypeVar
from . import exc as orm_exc
from . import path_registry
from ..sql.base import ExecutableOption
from ..sql.cache_key import HasCacheKey
+_T = TypeVar("_T", bound=Any)
__all__ = (
"EXT_CONTINUE",
@inspection._self_inspects
class MapperProperty(
- HasCacheKey, _MappedAttribute, InspectionAttr, util.MemoizedSlots
+ HasCacheKey, _MappedAttribute[_T], InspectionAttr, util.MemoizedSlots
):
"""Represent a particular class attribute mapped by :class:`_orm.Mapper`.
available in :class:`~sqlalchemy.orm.`.
"""
-
from collections import deque
from functools import reduce
from itertools import chain
import sys
+from typing import Generic
+from typing import Type
+from typing import TypeVar
import weakref
from . import attributes
_mapper_registries = weakref.WeakKeyDictionary()
+_MC = TypeVar("_MC")
+
+
def _all_registries():
with _CONFIGURE_MUTEX:
return set(_mapper_registries)
ORMEntityColumnsClauseRole,
sql_base.MemoizedHasCacheKey,
InspectionAttr,
+ Generic[_MC],
):
"""Defines an association between a Python class and a database table or
other relational structure, so that ORM operations against the class may
)
def __init__(
self,
- class_,
+ class_: Type[_MC],
local_table=None,
properties=None,
primary_key=None,
"""
+from typing import Any
+from typing import Generic
+from typing import TypeVar
+
from . import attributes
from . import strategy_options
from .descriptor_props import CompositeProperty
from .relationships import RelationshipProperty
from .util import _orm_full_deannotate
from .. import log
+from .. import sql
from .. import util
from ..sql import coercions
from ..sql import roles
+_T = TypeVar("_T", bound=Any)
__all__ = [
"ColumnProperty",
@log.class_logger
-class ColumnProperty(StrategizedProperty):
+class ColumnProperty(StrategizedProperty, Generic[_T]):
"""Describes an object attribute that corresponds to a table column.
Public constructor is the :func:`_orm.column_property` function.
"raiseload",
)
- def __init__(self, *columns, **kwargs):
- r"""Provide a column-level property for use with a mapping.
-
- Column-based properties can normally be applied to the mapper's
- ``properties`` dictionary using the :class:`_schema.Column`
- element directly.
- Use this function when the given column is not directly present within
- the mapper's selectable; examples include SQL expressions, functions,
- and scalar SELECT queries.
-
- The :func:`_orm.column_property` function returns an instance of
- :class:`.ColumnProperty`.
-
- Columns that aren't present in the mapper's selectable won't be
- persisted by the mapper and are effectively "read-only" attributes.
-
- :param \*cols:
- list of Column objects to be mapped.
-
- :param active_history=False:
- When ``True``, indicates that the "previous" value for a
- scalar attribute should be loaded when replaced, if not
- already loaded. Normally, history tracking logic for
- simple non-primary-key scalar values only needs to be
- aware of the "new" value in order to perform a flush. This
- flag is available for applications that make use of
- :func:`.attributes.get_history` or :meth:`.Session.is_modified`
- which also need to know
- the "previous" value of the attribute.
-
- :param comparator_factory: a class which extends
- :class:`.ColumnProperty.Comparator` which provides custom SQL
- clause generation for comparison operations.
-
- :param group:
- a group name for this property when marked as deferred.
-
- :param deferred:
- when True, the column property is "deferred", meaning that
- it does not load immediately, and is instead loaded when the
- attribute is first accessed on an instance. See also
- :func:`~sqlalchemy.orm.deferred`.
-
- :param doc:
- optional string that will be applied as the doc on the
- class-bound descriptor.
-
- :param expire_on_flush=True:
- Disable expiry on flush. A column_property() which refers
- to a SQL expression (and not a single table-bound column)
- is considered to be a "read only" property; populating it
- has no effect on the state of data, and it can only return
- database state. For this reason a column_property()'s value
- is expired whenever the parent object is involved in a
- flush, that is, has any kind of "dirty" state within a flush.
- Setting this parameter to ``False`` will have the effect of
- leaving any existing value present after the flush proceeds.
- Note however that the :class:`.Session` with default expiration
- settings still expires
- all attributes after a :meth:`.Session.commit` call, however.
-
- :param info: Optional data dictionary which will be populated into the
- :attr:`.MapperProperty.info` attribute of this object.
-
- :param raiseload: if True, indicates the column should raise an error
- when undeferred, rather than loading the value. This can be
- altered at query time by using the :func:`.deferred` option with
- raiseload=False.
-
- .. versionadded:: 1.4
-
- .. seealso::
-
- :ref:`deferred_raiseload`
-
- .. seealso::
-
- :ref:`column_property_options` - to map columns while including
- mapping options
-
- :ref:`mapper_column_property_sql_expressions` - to map SQL
- expressions
-
- """
+ def __init__(
+ self, column: sql.ColumnElement[_T], *additional_columns, **kwargs
+ ):
super(ColumnProperty, self).__init__()
+ columns = (column,) + additional_columns
self._orig_columns = [
coercions.expect(roles.LabeledColumnExprRole, c) for c in columns
]
class AliasOption(interfaces.LoaderOption):
+ inherit_cache = False
+
@util.deprecated(
"1.4",
"The :class:`.AliasOption` is not necessary "
"""
- inherit_cache = False
-
def process_compile_state(self, compile_state):
pass
"""
import collections
import re
+from typing import Callable
+from typing import Generic
+from typing import Type
+from typing import TypeVar
+from typing import Union
import weakref
from . import attributes
from ..sql.util import selectables_overlap
from ..sql.util import visit_binary_product
+_RC = TypeVar("_RC")
+
def remote(expr):
"""Annotate a portion of a primaryjoin expression
@log.class_logger
-class RelationshipProperty(StrategizedProperty):
+class RelationshipProperty(StrategizedProperty, Generic[_RC]):
"""Describes an object property that holds a single item or list
of items that correspond to a related database table.
def __init__(
self,
- argument,
+ argument: Union[str, Type[_RC], Callable[[], Type[_RC]]],
secondary=None,
primaryjoin=None,
secondaryjoin=None,
sync_backref=None,
_legacy_inactive_history_style=False,
):
- """Provide a relationship between two mapped classes.
-
- This corresponds to a parent-child or associative table relationship.
- The constructed class is an instance of
- :class:`.RelationshipProperty`.
-
- A typical :func:`_orm.relationship`, used in a classical mapping::
-
- mapper(Parent, properties={
- 'children': relationship(Child)
- })
-
- Some arguments accepted by :func:`_orm.relationship`
- optionally accept a
- callable function, which when called produces the desired value.
- The callable is invoked by the parent :class:`_orm.Mapper` at "mapper
- initialization" time, which happens only when mappers are first used,
- and is assumed to be after all mappings have been constructed. This
- can be used to resolve order-of-declaration and other dependency
- issues, such as if ``Child`` is declared below ``Parent`` in the same
- file::
-
- mapper(Parent, properties={
- "children":relationship(lambda: Child,
- order_by=lambda: Child.id)
- })
-
- When using the :ref:`declarative_toplevel` extension, the Declarative
- initializer allows string arguments to be passed to
- :func:`_orm.relationship`. These string arguments are converted into
- callables that evaluate the string as Python code, using the
- Declarative class-registry as a namespace. This allows the lookup of
- related classes to be automatic via their string name, and removes the
- need for related classes to be imported into the local module space
- before the dependent classes have been declared. It is still required
- that the modules in which these related classes appear are imported
- anywhere in the application at some point before the related mappings
- are actually used, else a lookup error will be raised when the
- :func:`_orm.relationship`
- attempts to resolve the string reference to the
- related class. An example of a string- resolved class is as
- follows::
-
- from sqlalchemy.ext.declarative import declarative_base
-
- Base = declarative_base()
-
- class Parent(Base):
- __tablename__ = 'parent'
- id = Column(Integer, primary_key=True)
- children = relationship("Child", order_by="Child.id")
-
- .. seealso::
-
- :ref:`relationship_config_toplevel` - Full introductory and
- reference documentation for :func:`_orm.relationship`.
-
- :ref:`orm_tutorial_relationship` - ORM tutorial introduction.
-
- :param argument:
- A mapped class, or actual :class:`_orm.Mapper` instance,
- representing
- the target of the relationship.
-
- :paramref:`_orm.relationship.argument`
- may also be passed as a callable
- function which is evaluated at mapper initialization time, and may
- be passed as a string name when using Declarative.
-
- .. warning:: Prior to SQLAlchemy 1.3.16, this value is interpreted
- using Python's ``eval()`` function.
- **DO NOT PASS UNTRUSTED INPUT TO THIS STRING**.
- See :ref:`declarative_relationship_eval` for details on
- declarative evaluation of :func:`_orm.relationship` arguments.
-
- .. versionchanged 1.3.16::
-
- The string evaluation of the main "argument" no longer accepts an
- open ended Python expression, instead only accepting a string
- class name or dotted package-qualified name.
-
- .. seealso::
-
- :ref:`declarative_configuring_relationships` - further detail
- on relationship configuration when using Declarative.
-
- :param secondary:
- For a many-to-many relationship, specifies the intermediary
- table, and is typically an instance of :class:`_schema.Table`.
- In less common circumstances, the argument may also be specified
- as an :class:`_expression.Alias` construct, or even a
- :class:`_expression.Join` construct.
-
- :paramref:`_orm.relationship.secondary` may
- also be passed as a callable function which is evaluated at
- mapper initialization time. When using Declarative, it may also
- be a string argument noting the name of a :class:`_schema.Table`
- that is
- present in the :class:`_schema.MetaData`
- collection associated with the
- parent-mapped :class:`_schema.Table`.
-
- .. warning:: When passed as a Python-evaluable string, the
- argument is interpreted using Python's ``eval()`` function.
- **DO NOT PASS UNTRUSTED INPUT TO THIS STRING**.
- See :ref:`declarative_relationship_eval` for details on
- declarative evaluation of :func:`_orm.relationship` arguments.
-
- The :paramref:`_orm.relationship.secondary` keyword argument is
- typically applied in the case where the intermediary
- :class:`_schema.Table`
- is not otherwise expressed in any direct class mapping. If the
- "secondary" table is also explicitly mapped elsewhere (e.g. as in
- :ref:`association_pattern`), one should consider applying the
- :paramref:`_orm.relationship.viewonly` flag so that this
- :func:`_orm.relationship`
- is not used for persistence operations which
- may conflict with those of the association object pattern.
-
- .. seealso::
-
- :ref:`relationships_many_to_many` - Reference example of "many
- to many".
-
- :ref:`orm_tutorial_many_to_many` - ORM tutorial introduction to
- many-to-many relationships.
-
- :ref:`self_referential_many_to_many` - Specifics on using
- many-to-many in a self-referential case.
-
- :ref:`declarative_many_to_many` - Additional options when using
- Declarative.
-
- :ref:`association_pattern` - an alternative to
- :paramref:`_orm.relationship.secondary`
- when composing association
- table relationships, allowing additional attributes to be
- specified on the association table.
-
- :ref:`composite_secondary_join` - a lesser-used pattern which
- in some cases can enable complex :func:`_orm.relationship` SQL
- conditions to be used.
-
- .. versionadded:: 0.9.2 :paramref:`_orm.relationship.secondary`
- works
- more effectively when referring to a :class:`_expression.Join`
- instance.
-
- :param active_history=False:
- When ``True``, indicates that the "previous" value for a
- many-to-one reference should be loaded when replaced, if
- not already loaded. Normally, history tracking logic for
- simple many-to-ones only needs to be aware of the "new"
- value in order to perform a flush. This flag is available
- for applications that make use of
- :func:`.attributes.get_history` which also need to know
- the "previous" value of the attribute.
-
- :param backref:
- Indicates the string name of a property to be placed on the related
- mapper's class that will handle this relationship in the other
- direction. The other property will be created automatically
- when the mappers are configured. Can also be passed as a
- :func:`.backref` object to control the configuration of the
- new relationship.
-
- .. seealso::
-
- :ref:`relationships_backref` - Introductory documentation and
- examples.
-
- :paramref:`_orm.relationship.back_populates` - alternative form
- of backref specification.
-
- :func:`.backref` - allows control over :func:`_orm.relationship`
- configuration when using :paramref:`_orm.relationship.backref`.
-
-
- :param back_populates:
- Takes a string name and has the same meaning as
- :paramref:`_orm.relationship.backref`, except the complementing
- property is **not** created automatically, and instead must be
- configured explicitly on the other mapper. The complementing
- property should also indicate
- :paramref:`_orm.relationship.back_populates` to this relationship to
- ensure proper functioning.
-
- .. seealso::
-
- :ref:`relationships_backref` - Introductory documentation and
- examples.
-
- :paramref:`_orm.relationship.backref` - alternative form
- of backref specification.
-
- :param overlaps:
- A string name or comma-delimited set of names of other relationships
- on either this mapper, a descendant mapper, or a target mapper with
- which this relationship may write to the same foreign keys upon
- persistence. The only effect this has is to eliminate the
- warning that this relationship will conflict with another upon
- persistence. This is used for such relationships that are truly
- capable of conflicting with each other on write, but the application
- will ensure that no such conflicts occur.
-
- .. versionadded:: 1.4
-
- .. seealso::
-
- :ref:`error_qzyx` - usage example
-
- :param bake_queries=True:
- Enable :ref:`lambda caching <engine_lambda_caching>` for loader
- strategies, if applicable, which adds a performance gain to the
- construction of SQL constructs used by loader strategies, in addition
- to the usual SQL statement caching used throughout SQLAlchemy. This
- parameter currently applies only to the "lazy" and "selectin" loader
- strategies. There is generally no reason to set this parameter to
- False.
-
- .. versionchanged:: 1.4 Relationship loaders no longer use the
- previous "baked query" system of query caching. The "lazy"
- and "selectin" loaders make use of the "lambda cache" system
- for the construction of SQL constructs,
- as well as the usual SQL caching system that is throughout
- SQLAlchemy as of the 1.4 series.
-
- :param cascade:
- A comma-separated list of cascade rules which determines how
- Session operations should be "cascaded" from parent to child.
- This defaults to ``False``, which means the default cascade
- should be used - this default cascade is ``"save-update, merge"``.
-
- The available cascades are ``save-update``, ``merge``,
- ``expunge``, ``delete``, ``delete-orphan``, and ``refresh-expire``.
- An additional option, ``all`` indicates shorthand for
- ``"save-update, merge, refresh-expire,
- expunge, delete"``, and is often used as in ``"all, delete-orphan"``
- to indicate that related objects should follow along with the
- parent object in all cases, and be deleted when de-associated.
-
- .. seealso::
-
- :ref:`unitofwork_cascades` - Full detail on each of the available
- cascade options.
-
- :ref:`tutorial_delete_cascade` - Tutorial example describing
- a delete cascade.
-
- :param cascade_backrefs=False:
- Legacy; this flag is always False.
-
- .. versionchanged:: 2.0 "cascade_backrefs" functionality has been
- removed.
-
- :param collection_class:
- A class or callable that returns a new list-holding object. will
- be used in place of a plain list for storing elements.
-
- .. seealso::
-
- :ref:`custom_collections` - Introductory documentation and
- examples.
-
- :param comparator_factory:
- A class which extends :class:`.RelationshipProperty.Comparator`
- which provides custom SQL clause generation for comparison
- operations.
-
- .. seealso::
-
- :class:`.PropComparator` - some detail on redefining comparators
- at this level.
-
- :ref:`custom_comparators` - Brief intro to this feature.
-
-
- :param distinct_target_key=None:
- Indicate if a "subquery" eager load should apply the DISTINCT
- keyword to the innermost SELECT statement. When left as ``None``,
- the DISTINCT keyword will be applied in those cases when the target
- columns do not comprise the full primary key of the target table.
- When set to ``True``, the DISTINCT keyword is applied to the
- innermost SELECT unconditionally.
-
- It may be desirable to set this flag to False when the DISTINCT is
- reducing performance of the innermost subquery beyond that of what
- duplicate innermost rows may be causing.
-
- .. versionchanged:: 0.9.0 -
- :paramref:`_orm.relationship.distinct_target_key` now defaults to
- ``None``, so that the feature enables itself automatically for
- those cases where the innermost query targets a non-unique
- key.
-
- .. seealso::
-
- :ref:`loading_toplevel` - includes an introduction to subquery
- eager loading.
-
- :param doc:
- Docstring which will be applied to the resulting descriptor.
-
- :param foreign_keys:
-
- A list of columns which are to be used as "foreign key"
- columns, or columns which refer to the value in a remote
- column, within the context of this :func:`_orm.relationship`
- object's :paramref:`_orm.relationship.primaryjoin` condition.
- That is, if the :paramref:`_orm.relationship.primaryjoin`
- condition of this :func:`_orm.relationship` is ``a.id ==
- b.a_id``, and the values in ``b.a_id`` are required to be
- present in ``a.id``, then the "foreign key" column of this
- :func:`_orm.relationship` is ``b.a_id``.
-
- In normal cases, the :paramref:`_orm.relationship.foreign_keys`
- parameter is **not required.** :func:`_orm.relationship` will
- automatically determine which columns in the
- :paramref:`_orm.relationship.primaryjoin` condition are to be
- considered "foreign key" columns based on those
- :class:`_schema.Column` objects that specify
- :class:`_schema.ForeignKey`,
- or are otherwise listed as referencing columns in a
- :class:`_schema.ForeignKeyConstraint` construct.
- :paramref:`_orm.relationship.foreign_keys` is only needed when:
-
- 1. There is more than one way to construct a join from the local
- table to the remote table, as there are multiple foreign key
- references present. Setting ``foreign_keys`` will limit the
- :func:`_orm.relationship`
- to consider just those columns specified
- here as "foreign".
-
- 2. The :class:`_schema.Table` being mapped does not actually have
- :class:`_schema.ForeignKey` or
- :class:`_schema.ForeignKeyConstraint`
- constructs present, often because the table
- was reflected from a database that does not support foreign key
- reflection (MySQL MyISAM).
-
- 3. The :paramref:`_orm.relationship.primaryjoin`
- argument is used to
- construct a non-standard join condition, which makes use of
- columns or expressions that do not normally refer to their
- "parent" column, such as a join condition expressed by a
- complex comparison using a SQL function.
-
- The :func:`_orm.relationship` construct will raise informative
- error messages that suggest the use of the
- :paramref:`_orm.relationship.foreign_keys` parameter when
- presented with an ambiguous condition. In typical cases,
- if :func:`_orm.relationship` doesn't raise any exceptions, the
- :paramref:`_orm.relationship.foreign_keys` parameter is usually
- not needed.
-
- :paramref:`_orm.relationship.foreign_keys` may also be passed as a
- callable function which is evaluated at mapper initialization time,
- and may be passed as a Python-evaluable string when using
- Declarative.
-
- .. warning:: When passed as a Python-evaluable string, the
- argument is interpreted using Python's ``eval()`` function.
- **DO NOT PASS UNTRUSTED INPUT TO THIS STRING**.
- See :ref:`declarative_relationship_eval` for details on
- declarative evaluation of :func:`_orm.relationship` arguments.
-
- .. seealso::
-
- :ref:`relationship_foreign_keys`
-
- :ref:`relationship_custom_foreign`
-
- :func:`.foreign` - allows direct annotation of the "foreign"
- columns within a :paramref:`_orm.relationship.primaryjoin`
- condition.
-
- :param info: Optional data dictionary which will be populated into the
- :attr:`.MapperProperty.info` attribute of this object.
-
- :param innerjoin=False:
- When ``True``, joined eager loads will use an inner join to join
- against related tables instead of an outer join. The purpose
- of this option is generally one of performance, as inner joins
- generally perform better than outer joins.
-
- This flag can be set to ``True`` when the relationship references an
- object via many-to-one using local foreign keys that are not
- nullable, or when the reference is one-to-one or a collection that
- is guaranteed to have one or at least one entry.
-
- The option supports the same "nested" and "unnested" options as
- that of :paramref:`_orm.joinedload.innerjoin`. See that flag
- for details on nested / unnested behaviors.
-
- .. seealso::
-
- :paramref:`_orm.joinedload.innerjoin` - the option as specified by
- loader option, including detail on nesting behavior.
-
- :ref:`what_kind_of_loading` - Discussion of some details of
- various loader options.
-
-
- :param join_depth:
- When non-``None``, an integer value indicating how many levels
- deep "eager" loaders should join on a self-referring or cyclical
- relationship. The number counts how many times the same Mapper
- shall be present in the loading condition along a particular join
- branch. When left at its default of ``None``, eager loaders
- will stop chaining when they encounter a the same target mapper
- which is already higher up in the chain. This option applies
- both to joined- and subquery- eager loaders.
-
- .. seealso::
-
- :ref:`self_referential_eager_loading` - Introductory documentation
- and examples.
-
- :param lazy='select': specifies
- How the related items should be loaded. Default value is
- ``select``. Values include:
-
- * ``select`` - items should be loaded lazily when the property is
- first accessed, using a separate SELECT statement, or identity map
- fetch for simple many-to-one references.
-
- * ``immediate`` - items should be loaded as the parents are loaded,
- using a separate SELECT statement, or identity map fetch for
- simple many-to-one references.
-
- * ``joined`` - items should be loaded "eagerly" in the same query as
- that of the parent, using a JOIN or LEFT OUTER JOIN. Whether
- the join is "outer" or not is determined by the
- :paramref:`_orm.relationship.innerjoin` parameter.
-
- * ``subquery`` - items should be loaded "eagerly" as the parents are
- loaded, using one additional SQL statement, which issues a JOIN to
- a subquery of the original statement, for each collection
- requested.
-
- * ``selectin`` - items should be loaded "eagerly" as the parents
- are loaded, using one or more additional SQL statements, which
- issues a JOIN to the immediate parent object, specifying primary
- key identifiers using an IN clause.
-
- .. versionadded:: 1.2
-
- * ``noload`` - no loading should occur at any time. This is to
- support "write-only" attributes, or attributes which are
- populated in some manner specific to the application.
-
- * ``raise`` - lazy loading is disallowed; accessing
- the attribute, if its value were not already loaded via eager
- loading, will raise an :exc:`~sqlalchemy.exc.InvalidRequestError`.
- This strategy can be used when objects are to be detached from
- their attached :class:`.Session` after they are loaded.
-
- .. versionadded:: 1.1
-
- * ``raise_on_sql`` - lazy loading that emits SQL is disallowed;
- accessing the attribute, if its value were not already loaded via
- eager loading, will raise an
- :exc:`~sqlalchemy.exc.InvalidRequestError`, **if the lazy load
- needs to emit SQL**. If the lazy load can pull the related value
- from the identity map or determine that it should be None, the
- value is loaded. This strategy can be used when objects will
- remain associated with the attached :class:`.Session`, however
- additional SELECT statements should be blocked.
-
- .. versionadded:: 1.1
-
- * ``dynamic`` - the attribute will return a pre-configured
- :class:`_query.Query` object for all read
- operations, onto which further filtering operations can be
- applied before iterating the results. See
- the section :ref:`dynamic_relationship` for more details.
-
- * True - a synonym for 'select'
-
- * False - a synonym for 'joined'
-
- * None - a synonym for 'noload'
-
- .. seealso::
-
- :doc:`/orm/loading_relationships` - Full documentation on
- relationship loader configuration.
-
- :ref:`dynamic_relationship` - detail on the ``dynamic`` option.
-
- :ref:`collections_noload_raiseload` - notes on "noload" and "raise"
-
- :param load_on_pending=False:
- Indicates loading behavior for transient or pending parent objects.
-
- When set to ``True``, causes the lazy-loader to
- issue a query for a parent object that is not persistent, meaning it
- has never been flushed. This may take effect for a pending object
- when autoflush is disabled, or for a transient object that has been
- "attached" to a :class:`.Session` but is not part of its pending
- collection.
-
- The :paramref:`_orm.relationship.load_on_pending`
- flag does not improve
- behavior when the ORM is used normally - object references should be
- constructed at the object level, not at the foreign key level, so
- that they are present in an ordinary way before a flush proceeds.
- This flag is not not intended for general use.
-
- .. seealso::
-
- :meth:`.Session.enable_relationship_loading` - this method
- establishes "load on pending" behavior for the whole object, and
- also allows loading on objects that remain transient or
- detached.
-
- :param order_by:
- Indicates the ordering that should be applied when loading these
- items. :paramref:`_orm.relationship.order_by`
- is expected to refer to
- one of the :class:`_schema.Column`
- objects to which the target class is
- mapped, or the attribute itself bound to the target class which
- refers to the column.
-
- :paramref:`_orm.relationship.order_by`
- may also be passed as a callable
- function which is evaluated at mapper initialization time, and may
- be passed as a Python-evaluable string when using Declarative.
-
- .. warning:: When passed as a Python-evaluable string, the
- argument is interpreted using Python's ``eval()`` function.
- **DO NOT PASS UNTRUSTED INPUT TO THIS STRING**.
- See :ref:`declarative_relationship_eval` for details on
- declarative evaluation of :func:`_orm.relationship` arguments.
-
- :param passive_deletes=False:
- Indicates loading behavior during delete operations.
-
- A value of True indicates that unloaded child items should not
- be loaded during a delete operation on the parent. Normally,
- when a parent item is deleted, all child items are loaded so
- that they can either be marked as deleted, or have their
- foreign key to the parent set to NULL. Marking this flag as
- True usually implies an ON DELETE <CASCADE|SET NULL> rule is in
- place which will handle updating/deleting child rows on the
- database side.
-
- Additionally, setting the flag to the string value 'all' will
- disable the "nulling out" of the child foreign keys, when the parent
- object is deleted and there is no delete or delete-orphan cascade
- enabled. This is typically used when a triggering or error raise
- scenario is in place on the database side. Note that the foreign
- key attributes on in-session child objects will not be changed after
- a flush occurs so this is a very special use-case setting.
- Additionally, the "nulling out" will still occur if the child
- object is de-associated with the parent.
-
- .. seealso::
-
- :ref:`passive_deletes` - Introductory documentation
- and examples.
-
- :param passive_updates=True:
- Indicates the persistence behavior to take when a referenced
- primary key value changes in place, indicating that the referencing
- foreign key columns will also need their value changed.
-
- When True, it is assumed that ``ON UPDATE CASCADE`` is configured on
- the foreign key in the database, and that the database will
- handle propagation of an UPDATE from a source column to
- dependent rows. When False, the SQLAlchemy
- :func:`_orm.relationship`
- construct will attempt to emit its own UPDATE statements to
- modify related targets. However note that SQLAlchemy **cannot**
- emit an UPDATE for more than one level of cascade. Also,
- setting this flag to False is not compatible in the case where
- the database is in fact enforcing referential integrity, unless
- those constraints are explicitly "deferred", if the target backend
- supports it.
-
- It is highly advised that an application which is employing
- mutable primary keys keeps ``passive_updates`` set to True,
- and instead uses the referential integrity features of the database
- itself in order to handle the change efficiently and fully.
-
- .. seealso::
-
- :ref:`passive_updates` - Introductory documentation and
- examples.
-
- :paramref:`.mapper.passive_updates` - a similar flag which
- takes effect for joined-table inheritance mappings.
-
- :param post_update:
- This indicates that the relationship should be handled by a
- second UPDATE statement after an INSERT or before a
- DELETE. Currently, it also will issue an UPDATE after the
- instance was UPDATEd as well, although this technically should
- be improved. This flag is used to handle saving bi-directional
- dependencies between two individual rows (i.e. each row
- references the other), where it would otherwise be impossible to
- INSERT or DELETE both rows fully since one row exists before the
- other. Use this flag when a particular mapping arrangement will
- incur two rows that are dependent on each other, such as a table
- that has a one-to-many relationship to a set of child rows, and
- also has a column that references a single child row within that
- list (i.e. both tables contain a foreign key to each other). If
- a flush operation returns an error that a "cyclical
- dependency" was detected, this is a cue that you might want to
- use :paramref:`_orm.relationship.post_update` to "break" the cycle.
-
- .. seealso::
-
- :ref:`post_update` - Introductory documentation and examples.
-
- :param primaryjoin:
- A SQL expression that will be used as the primary
- join of the child object against the parent object, or in a
- many-to-many relationship the join of the parent object to the
- association table. By default, this value is computed based on the
- foreign key relationships of the parent and child tables (or
- association table).
-
- :paramref:`_orm.relationship.primaryjoin` may also be passed as a
- callable function which is evaluated at mapper initialization time,
- and may be passed as a Python-evaluable string when using
- Declarative.
-
- .. warning:: When passed as a Python-evaluable string, the
- argument is interpreted using Python's ``eval()`` function.
- **DO NOT PASS UNTRUSTED INPUT TO THIS STRING**.
- See :ref:`declarative_relationship_eval` for details on
- declarative evaluation of :func:`_orm.relationship` arguments.
-
- .. seealso::
-
- :ref:`relationship_primaryjoin`
-
- :param remote_side:
- Used for self-referential relationships, indicates the column or
- list of columns that form the "remote side" of the relationship.
-
- :paramref:`_orm.relationship.remote_side` may also be passed as a
- callable function which is evaluated at mapper initialization time,
- and may be passed as a Python-evaluable string when using
- Declarative.
-
- .. warning:: When passed as a Python-evaluable string, the
- argument is interpreted using Python's ``eval()`` function.
- **DO NOT PASS UNTRUSTED INPUT TO THIS STRING**.
- See :ref:`declarative_relationship_eval` for details on
- declarative evaluation of :func:`_orm.relationship` arguments.
-
- .. seealso::
-
- :ref:`self_referential` - in-depth explanation of how
- :paramref:`_orm.relationship.remote_side`
- is used to configure self-referential relationships.
-
- :func:`.remote` - an annotation function that accomplishes the
- same purpose as :paramref:`_orm.relationship.remote_side`,
- typically
- when a custom :paramref:`_orm.relationship.primaryjoin` condition
- is used.
-
- :param query_class:
- A :class:`_query.Query`
- subclass that will be used internally by the
- ``AppenderQuery`` returned by a "dynamic" relationship, that
- is, a relationship that specifies ``lazy="dynamic"`` or was
- otherwise constructed using the :func:`_orm.dynamic_loader`
- function.
-
- .. seealso::
-
- :ref:`dynamic_relationship` - Introduction to "dynamic"
- relationship loaders.
-
- :param secondaryjoin:
- A SQL expression that will be used as the join of
- an association table to the child object. By default, this value is
- computed based on the foreign key relationships of the association
- and child tables.
-
- :paramref:`_orm.relationship.secondaryjoin` may also be passed as a
- callable function which is evaluated at mapper initialization time,
- and may be passed as a Python-evaluable string when using
- Declarative.
-
- .. warning:: When passed as a Python-evaluable string, the
- argument is interpreted using Python's ``eval()`` function.
- **DO NOT PASS UNTRUSTED INPUT TO THIS STRING**.
- See :ref:`declarative_relationship_eval` for details on
- declarative evaluation of :func:`_orm.relationship` arguments.
-
- .. seealso::
-
- :ref:`relationship_primaryjoin`
-
- :param single_parent:
- When True, installs a validator which will prevent objects
- from being associated with more than one parent at a time.
- This is used for many-to-one or many-to-many relationships that
- should be treated either as one-to-one or one-to-many. Its usage
- is optional, except for :func:`_orm.relationship` constructs which
- are many-to-one or many-to-many and also
- specify the ``delete-orphan`` cascade option. The
- :func:`_orm.relationship` construct itself will raise an error
- instructing when this option is required.
-
- .. seealso::
-
- :ref:`unitofwork_cascades` - includes detail on when the
- :paramref:`_orm.relationship.single_parent`
- flag may be appropriate.
-
- :param uselist:
- A boolean that indicates if this property should be loaded as a
- list or a scalar. In most cases, this value is determined
- automatically by :func:`_orm.relationship` at mapper configuration
- time, based on the type and direction
- of the relationship - one to many forms a list, many to one
- forms a scalar, many to many is a list. If a scalar is desired
- where normally a list would be present, such as a bi-directional
- one-to-one relationship, set :paramref:`_orm.relationship.uselist`
- to
- False.
-
- The :paramref:`_orm.relationship.uselist`
- flag is also available on an
- existing :func:`_orm.relationship`
- construct as a read-only attribute,
- which can be used to determine if this :func:`_orm.relationship`
- deals
- with collections or scalar attributes::
-
- >>> User.addresses.property.uselist
- True
-
- .. seealso::
-
- :ref:`relationships_one_to_one` - Introduction to the "one to
- one" relationship pattern, which is typically when the
- :paramref:`_orm.relationship.uselist` flag is needed.
-
- :param viewonly=False:
- When set to ``True``, the relationship is used only for loading
- objects, and not for any persistence operation. A
- :func:`_orm.relationship` which specifies
- :paramref:`_orm.relationship.viewonly` can work
- with a wider range of SQL operations within the
- :paramref:`_orm.relationship.primaryjoin` condition, including
- operations that feature the use of a variety of comparison operators
- as well as SQL functions such as :func:`_expression.cast`. The
- :paramref:`_orm.relationship.viewonly`
- flag is also of general use when defining any kind of
- :func:`_orm.relationship` that doesn't represent
- the full set of related objects, to prevent modifications of the
- collection from resulting in persistence operations.
-
- When using the :paramref:`_orm.relationship.viewonly` flag in
- conjunction with backrefs, the originating relationship for a
- particular state change will not produce state changes within the
- viewonly relationship. This is the behavior implied by
- :paramref:`_orm.relationship.sync_backref` being set to False.
-
- .. versionchanged:: 1.3.17 - the
- :paramref:`_orm.relationship.sync_backref` flag is set to False
- when using viewonly in conjunction with backrefs.
-
- .. seealso::
-
- :paramref:`_orm.relationship.sync_backref`
-
- :param sync_backref:
- A boolean that enables the events used to synchronize the in-Python
- attributes when this relationship is target of either
- :paramref:`_orm.relationship.backref` or
- :paramref:`_orm.relationship.back_populates`.
-
- Defaults to ``None``, which indicates that an automatic value should
- be selected based on the value of the
- :paramref:`_orm.relationship.viewonly` flag. When left at its
- default, changes in state will be back-populated only if neither
- sides of a relationship is viewonly.
-
- .. versionadded:: 1.3.17
-
- .. versionchanged:: 1.4 - A relationship that specifies
- :paramref:`_orm.relationship.viewonly` automatically implies
- that :paramref:`_orm.relationship.sync_backref` is ``False``.
-
- .. seealso::
-
- :paramref:`_orm.relationship.viewonly`
-
- :param omit_join:
- Allows manual control over the "selectin" automatic join
- optimization. Set to ``False`` to disable the "omit join" feature
- added in SQLAlchemy 1.3; or leave as ``None`` to leave automatic
- optimization in place.
-
- .. note:: This flag may only be set to ``False``. It is not
- necessary to set it to ``True`` as the "omit_join" optimization is
- automatically detected; if it is not detected, then the
- optimization is not supported.
-
- .. versionchanged:: 1.3.11 setting ``omit_join`` to True will now
- emit a warning as this was not the intended use of this flag.
-
- .. versionadded:: 1.3
-
-
- """
super(RelationshipProperty, self).__init__()
self.uselist = uselist
# This module is part of SQLAlchemy and is released under
# the MIT License: https://www.opensource.org/licenses/mit-license.php
-from . import class_mapper
from . import exc as orm_exc
+from .base import class_mapper
from .session import Session
from .. import exc as sa_exc
from ..util import create_proxy_methods
propagate_to_loaders=True,
track_closure_variables=True,
):
- """Add additional WHERE criteria to the load for all occurrences of
- a particular entity.
-
- .. versionadded:: 1.4
-
- The :func:`_orm.with_loader_criteria` option is intended to add
- limiting criteria to a particular kind of entity in a query,
- **globally**, meaning it will apply to the entity as it appears
- in the SELECT query as well as within any subqueries, join
- conditions, and relationship loads, including both eager and lazy
- loaders, without the need for it to be specified in any particular
- part of the query. The rendering logic uses the same system used by
- single table inheritance to ensure a certain discriminator is applied
- to a table.
-
- E.g., using :term:`2.0-style` queries, we can limit the way the
- ``User.addresses`` collection is loaded, regardless of the kind
- of loading used::
-
- from sqlalchemy.orm import with_loader_criteria
-
- stmt = select(User).options(
- selectinload(User.addresses),
- with_loader_criteria(Address, Address.email_address != 'foo'))
- )
-
- Above, the "selectinload" for ``User.addresses`` will apply the
- given filtering criteria to the WHERE clause.
-
- Another example, where the filtering will be applied to the
- ON clause of the join, in this example using :term:`1.x style`
- queries::
-
- q = session.query(User).outerjoin(User.addresses).options(
- with_loader_criteria(Address, Address.email_address != 'foo'))
- )
-
- The primary purpose of :func:`_orm.with_loader_criteria` is to use
- it in the :meth:`_orm.SessionEvents.do_orm_execute` event handler
- to ensure that all occurrences of a particular entity are filtered
- in a certain way, such as filtering for access control roles. It
- also can be used to apply criteria to relationship loads. In the
- example below, we can apply a certain set of rules to all queries
- emitted by a particular :class:`_orm.Session`::
-
- session = Session(bind=engine)
-
- @event.listens_for("do_orm_execute", session)
- def _add_filtering_criteria(execute_state):
-
- if (
- execute_state.is_select
- and not execute_state.is_column_load
- and not execute_state.is_relationship_load
- ):
- execute_state.statement = execute_state.statement.options(
- with_loader_criteria(
- SecurityRole,
- lambda cls: cls.role.in_(['some_role']),
- include_aliases=True
- )
- )
-
- In the above example, the :meth:`_orm.SessionEvents.do_orm_execute`
- event will intercept all queries emitted using the
- :class:`_orm.Session`. For those queries which are SELECT statements
- and are not attribute or relationship loads a custom
- :func:`_orm.with_loader_criteria` option is added to the query. The
- :func:`_orm.with_loader_criteria` option will be used in the given
- statement and will also be automatically propagated to all relationship
- loads that descend from this query.
-
- The criteria argument given is a ``lambda`` that accepts a ``cls``
- argument. The given class will expand to include all mapped subclass
- and need not itself be a mapped class.
-
- .. tip::
-
- When using :func:`_orm.with_loader_criteria` option in
- conjunction with the :func:`_orm.contains_eager` loader option,
- it's important to note that :func:`_orm.with_loader_criteria` only
- affects the part of the query that determines what SQL is rendered
- in terms of the WHERE and FROM clauses. The
- :func:`_orm.contains_eager` option does not affect the rendering of
- the SELECT statement outside of the columns clause, so does not have
- any interaction with the :func:`_orm.with_loader_criteria` option.
- However, the way things "work" is that :func:`_orm.contains_eager`
- is meant to be used with a query that is already selecting from the
- additional entities in some way, where
- :func:`_orm.with_loader_criteria` can apply it's additional
- criteria.
-
- In the example below, assuming a mapping relationship as
- ``A -> A.bs -> B``, the given :func:`_orm.with_loader_criteria`
- option will affect the way in which the JOIN is rendered::
-
- stmt = select(A).join(A.bs).options(
- contains_eager(A.bs),
- with_loader_criteria(B, B.flag == 1)
- )
-
- Above, the given :func:`_orm.with_loader_criteria` option will
- affect the ON clause of the JOIN that is specified by
- ``.join(A.bs)``, so is applied as expected. The
- :func:`_orm.contains_eager` option has the effect that columns from
- ``B`` are added to the columns clause::
-
- SELECT
- b.id, b.a_id, b.data, b.flag,
- a.id AS id_1,
- a.data AS data_1
- FROM a JOIN b ON a.id = b.a_id AND b.flag = :flag_1
-
-
- The use of the :func:`_orm.contains_eager` option within the above
- statement has no effect on the behavior of the
- :func:`_orm.with_loader_criteria` option. If the
- :func:`_orm.contains_eager` option were omitted, the SQL would be
- the same as regards the FROM and WHERE clauses, where
- :func:`_orm.with_loader_criteria` continues to add its criteria to
- the ON clause of the JOIN. The addition of
- :func:`_orm.contains_eager` only affects the columns clause, in that
- additional columns against ``b`` are added which are then consumed
- by the ORM to produce ``B`` instances.
-
- .. warning:: The use of a lambda inside of the call to
- :func:`_orm.with_loader_criteria` is only invoked **once per unique
- class**. Custom functions should not be invoked within this lambda.
- See :ref:`engine_lambda_caching` for an overview of the "lambda SQL"
- feature, which is for advanced use only.
-
- :param entity_or_base: a mapped class, or a class that is a super
- class of a particular set of mapped classes, to which the rule
- will apply.
-
- :param where_criteria: a Core SQL expression that applies limiting
- criteria. This may also be a "lambda:" or Python function that
- accepts a target class as an argument, when the given class is
- a base with many different mapped subclasses.
-
- :param include_aliases: if True, apply the rule to :func:`_orm.aliased`
- constructs as well.
-
- :param propagate_to_loaders: defaults to True, apply to relationship
- loaders such as lazy loaders.
-
-
- .. seealso::
-
- :ref:`examples_session_orm_events` - includes examples of using
- :func:`_orm.with_loader_criteria`.
-
- :ref:`do_orm_execute_global_criteria` - basic example on how to
- combine :func:`_orm.with_loader_criteria` with the
- :meth:`_orm.SessionEvents.do_orm_execute` event.
-
- :param track_closure_variables: when False, closure variables inside
- of a lambda expression will not be used as part of
- any cache key. This allows more complex expressions to be used
- inside of a lambda expression but requires that the lambda ensures
- it returns the identical SQL every time given a particular class.
-
- .. versionadded:: 1.4.0b2
-
- """
-
entity = inspection.inspect(entity_or_base, False)
if entity is None:
self.root_entity = entity_or_base
# This module is part of SQLAlchemy and is released under
# the MIT License: https://www.opensource.org/licenses/mit-license.php
-from .base import Executable
-from .compiler import COLLECT_CARTESIAN_PRODUCTS
-from .compiler import FROM_LINTING
-from .compiler import NO_LINTING
-from .compiler import WARN_LINTING
-from .expression import Alias
-from .expression import alias
-from .expression import all_
-from .expression import and_
-from .expression import any_
-from .expression import asc
-from .expression import between
-from .expression import bindparam
-from .expression import case
-from .expression import cast
-from .expression import ClauseElement
-from .expression import collate
-from .expression import column
-from .expression import ColumnCollection
-from .expression import ColumnElement
-from .expression import CompoundSelect
-from .expression import cte
-from .expression import Delete
-from .expression import delete
-from .expression import desc
-from .expression import distinct
-from .expression import except_
-from .expression import except_all
-from .expression import exists
-from .expression import extract
-from .expression import false
-from .expression import False_
-from .expression import FromClause
-from .expression import func
-from .expression import funcfilter
-from .expression import Insert
-from .expression import insert
-from .expression import intersect
-from .expression import intersect_all
-from .expression import Join
-from .expression import join
-from .expression import label
-from .expression import LABEL_STYLE_DEFAULT
-from .expression import LABEL_STYLE_DISAMBIGUATE_ONLY
-from .expression import LABEL_STYLE_NONE
-from .expression import LABEL_STYLE_TABLENAME_PLUS_COL
-from .expression import lambda_stmt
-from .expression import LambdaElement
-from .expression import lateral
-from .expression import literal
-from .expression import literal_column
-from .expression import modifier
-from .expression import not_
-from .expression import null
-from .expression import nulls_first
-from .expression import nulls_last
-from .expression import nullsfirst
-from .expression import nullslast
-from .expression import or_
-from .expression import outerjoin
-from .expression import outparam
-from .expression import over
-from .expression import quoted_name
-from .expression import Select
-from .expression import select
-from .expression import Selectable
-from .expression import StatementLambdaElement
-from .expression import Subquery
-from .expression import table
-from .expression import TableClause
-from .expression import TableSample
-from .expression import tablesample
-from .expression import text
-from .expression import true
-from .expression import True_
-from .expression import tuple_
-from .expression import type_coerce
-from .expression import union
-from .expression import union_all
-from .expression import Update
-from .expression import update
-from .expression import Values
-from .expression import values
-from .expression import within_group
-from .visitors import ClauseVisitor
+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 .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 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 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 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):
- global __all__
- from .. import util as _sa_util
-
- import inspect as _inspect
-
- __all__ = sorted(
- name
- for name, obj in lcls.items()
- if not (name.startswith("_") or _inspect.ismodule(obj))
+if True:
+ # work around zimports bug
+ 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 .annotation import _prepare_annotations
- from .annotation import Annotated
- from .elements import AnnotatedColumnElement
- from .elements import ClauseList
- from .selectable import AnnotatedFromClause
- # from .traversals import _preconfigure_traversals
+def __go(lcls):
+ from .. import util as _sa_util
from . import base
from . import coercions
from . import elements
- from . import events
from . import lambdas
from . import selectable
from . import schema
- from . import sqltypes
from . import traversals
from . import type_api
coercions.lambdas = lambdas
coercions.schema = schema
coercions.selectable = selectable
- coercions.sqltypes = sqltypes
coercions.traversals = traversals
+ 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)
- # this is expensive at import time; elements that are used can create
- # their traversals on demand
- # _preconfigure_traversals(ClauseElement)
-
_sa_util.preloaded.import_prefix("sqlalchemy.sql")
- from . import naming
-
__go(locals())
--- /dev/null
+# sql/_dml_constructors.py
+# Copyright (C) 2005-2022 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 .dml import Delete
+from .dml import Insert
+from .dml import Update
+
+
+def insert(table):
+ """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:`coretutorial_insert_expressions` - in the
+ :ref:`1.x tutorial <sqlexpression_toplevel>`
+
+ :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:`coretutorial_insert_expressions` - SQL Expression Tutorial
+
+ :ref:`inserts_and_updates` - SQL Expression Tutorial
+
+ """
+ return Insert(table)
+
+
+def update(table):
+ 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`.
+
+ .. seealso::
+
+ :ref:`inserts_and_updates` - in the
+ :ref:`1.x tutorial <sqlexpression_toplevel>`
+
+ :ref:`tutorial_core_update_delete` - in the :ref:`unified_tutorial`
+
+
+
+ :param table: A :class:`_schema.Table`
+ object representing the database
+ table to be updated.
+
+ :param whereclause: Optional SQL expression describing the ``WHERE``
+ condition of the ``UPDATE`` statement; is equivalent to using the
+ more modern :meth:`~Update.where()` method to specify the ``WHERE``
+ clause.
+
+ :param values:
+ Optional dictionary which specifies the ``SET`` conditions of the
+ ``UPDATE``. If left as ``None``, the ``SET``
+ conditions are determined from those parameters passed to the
+ statement during the execution and/or compilation of the
+ statement. When compiled standalone without any parameters,
+ the ``SET`` clause generates for all columns.
+
+ Modern applications may prefer to use the generative
+ :meth:`_expression.Update.values` method to set the values of the
+ UPDATE statement.
+
+ :param inline:
+ if True, SQL defaults present on :class:`_schema.Column` objects via
+ the ``default`` keyword will be compiled 'inline' into the statement
+ and not pre-executed. This means that their values will not
+ be available in the dictionary returned from
+ :meth:`_engine.CursorResult.last_updated_params`.
+
+ :param preserve_parameter_order: if True, the update statement is
+ expected to receive parameters **only** via the
+ :meth:`_expression.Update.values` method,
+ and they must be passed as a Python
+ ``list`` of 2-tuples. The rendered UPDATE statement will emit the SET
+ clause for each referenced column maintaining this order.
+
+ .. versionadded:: 1.0.10
+
+ .. seealso::
+
+ :ref:`updates_order_parameters` - illustrates the
+ :meth:`_expression.Update.ordered_values` method.
+
+ If both ``values`` and compile-time bind parameters are present, the
+ compile-time bind parameters override the information specified
+ within ``values`` on a per-key basis.
+
+ The keys within ``values`` can be either :class:`_schema.Column`
+ objects or their string identifiers (specifically the "key" of the
+ :class:`_schema.Column`, normally but not necessarily equivalent to
+ its "name"). Normally, the
+ :class:`_schema.Column` objects used here are expected to be
+ part of the target :class:`_schema.Table` that is the table
+ to be updated. However when using MySQL, a multiple-table
+ UPDATE statement can refer to columns from any of
+ the tables referred to in the WHERE clause.
+
+ The values referred to in ``values`` are typically:
+
+ * a literal data value (i.e. string, number, etc.)
+ * a SQL expression, such as a related :class:`_schema.Column`,
+ a scalar-returning :func:`_expression.select` construct,
+ etc.
+
+ When combining :func:`_expression.select` constructs within the
+ values clause of an :func:`_expression.update`
+ construct, the subquery represented
+ by the :func:`_expression.select` should be *correlated* to the
+ parent table, that is, providing criterion which links the table inside
+ the subquery to the outer table being updated::
+
+ users.update().values(
+ name=select(addresses.c.email_address).\
+ where(addresses.c.user_id==users.c.id).\
+ scalar_subquery()
+ )
+
+ .. seealso::
+
+ :ref:`inserts_and_updates` - SQL Expression
+ Language Tutorial
+
+
+ """
+ return Update(table)
+
+
+def delete(table):
+ 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`.
+
+ .. seealso::
+
+ :ref:`inserts_and_updates` - in the
+ :ref:`1.x tutorial <sqlexpression_toplevel>`
+
+ :ref:`tutorial_core_update_delete` - in the :ref:`unified_tutorial`
+
+
+ :param table: The table to delete rows from.
+
+ :param whereclause: Optional SQL expression describing the ``WHERE``
+ condition of the ``DELETE`` statement; is equivalent to using the
+ more modern :meth:`~Delete.where()` method to specify the ``WHERE``
+ clause.
+
+ .. seealso::
+
+ :ref:`deletes` - SQL Expression Tutorial
+
+ """
+ return Delete(table)
--- /dev/null
+# sql/_elements_constructors.py
+# Copyright (C) 2005-2022 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
+
+import typing
+from typing import Any
+from typing import cast as _typing_cast
+from typing import Optional
+from typing import overload
+from typing import Type
+from typing import TypeVar
+from typing import Union
+
+from . import coercions
+from . import operators
+from . import roles
+from .base import NO_ARG
+from .coercions import _document_text_coercion
+from .elements import BindParameter
+from .elements import BooleanClauseList
+from .elements import Case
+from .elements import Cast
+from .elements import CollationClause
+from .elements import CollectionAggregate
+from .elements import ColumnClause
+from .elements import ColumnElement
+from .elements import Extract
+from .elements import False_
+from .elements import FunctionFilter
+from .elements import Label
+from .elements import Null
+from .elements import Over
+from .elements import TextClause
+from .elements import True_
+from .elements import Tuple
+from .elements import TypeCoerce
+from .elements import UnaryExpression
+from .elements import WithinGroup
+
+if typing.TYPE_CHECKING:
+ from elements import BinaryExpression
+
+ from . import sqltypes
+ from .functions import FunctionElement
+ from .selectable import FromClause
+ from .type_api import TypeEngine
+
+_T = TypeVar("_T")
+
+
+def all_(expr):
+ """Produce an ALL expression.
+
+ For dialects such as that of PostgreSQL, this operator applies
+ to usage of the :class:`_types.ARRAY` datatype, for that of
+ MySQL, it may apply to a subquery. e.g.::
+
+ # renders on PostgreSQL:
+ # '5 = ALL (somearray)'
+ expr = 5 == all_(mytable.c.somearray)
+
+ # renders on MySQL:
+ # '5 = ALL (SELECT value FROM table)'
+ expr = 5 == all_(select(table.c.value))
+
+ Comparison to NULL may work using ``None``::
+
+ None == all_(mytable.c.somearray)
+
+ The any_() / all_() operators also feature a special "operand flipping"
+ behavior such that if any_() / all_() are used on the left side of a
+ comparison using a standalone operator such as ``==``, ``!=``, etc.
+ (not including operator methods such as
+ :meth:`_sql.ColumnOperators.is_`) the rendered expression is flipped::
+
+ # would render '5 = ALL (column)`
+ all_(mytable.c.column) == 5
+
+ Or with ``None``, which note will not perform
+ the usual step of rendering "IS" as is normally the case for NULL::
+
+ # would render 'NULL = ALL(somearray)'
+ all_(mytable.c.somearray) == None
+
+ .. versionchanged:: 1.4.26 repaired the use of any_() / all_()
+ comparing to NULL on the right side to be flipped to the left.
+
+ The column-level :meth:`_sql.ColumnElement.all_` method (not to be
+ confused with :class:`_types.ARRAY` level
+ :meth:`_types.ARRAY.Comparator.all`) is shorthand for
+ ``all_(col)``::
+
+ 5 == mytable.c.somearray.all_()
+
+ .. seealso::
+
+ :meth:`_sql.ColumnOperators.all_`
+
+ :func:`_expression.any_`
+
+ """
+ return CollectionAggregate._create_all(expr)
+
+
+def and_(*clauses):
+ r"""Produce a conjunction of expressions joined by ``AND``.
+
+ E.g.::
+
+ from sqlalchemy import and_
+
+ stmt = select(users_table).where(
+ and_(
+ users_table.c.name == 'wendy',
+ users_table.c.enrolled == True
+ )
+ )
+
+ The :func:`.and_` conjunction is also available using the
+ Python ``&`` operator (though note that compound expressions
+ need to be parenthesized in order to function with Python
+ operator precedence behavior)::
+
+ stmt = select(users_table).where(
+ (users_table.c.name == 'wendy') &
+ (users_table.c.enrolled == True)
+ )
+
+ The :func:`.and_` operation is also implicit in some cases;
+ the :meth:`_expression.Select.where`
+ method for example can be invoked multiple
+ times against a statement, which will have the effect of each
+ clause being combined using :func:`.and_`::
+
+ stmt = select(users_table).\
+ where(users_table.c.name == 'wendy').\
+ where(users_table.c.enrolled == True)
+
+ The :func:`.and_` construct must be given at least one positional
+ argument in order to be valid; a :func:`.and_` construct with no
+ arguments is ambiguous. To produce an "empty" or dynamically
+ generated :func:`.and_` expression, from a given list of expressions,
+ a "default" element of ``True`` should be specified::
+
+ criteria = and_(True, *expressions)
+
+ The above expression will compile to SQL as the expression ``true``
+ or ``1 = 1``, depending on backend, if no other expressions are
+ present. If expressions are present, then the ``True`` value is
+ ignored as it does not affect the outcome of an AND expression that
+ has other elements.
+
+ .. deprecated:: 1.4 The :func:`.and_` element now requires that at
+ least one argument is passed; creating the :func:`.and_` construct
+ with no arguments is deprecated, and will emit a deprecation warning
+ while continuing to produce a blank SQL string.
+
+ .. seealso::
+
+ :func:`.or_`
+
+ """
+ return BooleanClauseList.and_(*clauses)
+
+
+def any_(expr):
+ """Produce an ANY expression.
+
+ For dialects such as that of PostgreSQL, this operator applies
+ to usage of the :class:`_types.ARRAY` datatype, for that of
+ MySQL, it may apply to a subquery. e.g.::
+
+ # renders on PostgreSQL:
+ # '5 = ANY (somearray)'
+ expr = 5 == any_(mytable.c.somearray)
+
+ # renders on MySQL:
+ # '5 = ANY (SELECT value FROM table)'
+ expr = 5 == any_(select(table.c.value))
+
+ Comparison to NULL may work using ``None`` or :func:`_sql.null`::
+
+ None == any_(mytable.c.somearray)
+
+ The any_() / all_() operators also feature a special "operand flipping"
+ behavior such that if any_() / all_() are used on the left side of a
+ comparison using a standalone operator such as ``==``, ``!=``, etc.
+ (not including operator methods such as
+ :meth:`_sql.ColumnOperators.is_`) the rendered expression is flipped::
+
+ # would render '5 = ANY (column)`
+ any_(mytable.c.column) == 5
+
+ Or with ``None``, which note will not perform
+ the usual step of rendering "IS" as is normally the case for NULL::
+
+ # would render 'NULL = ANY(somearray)'
+ any_(mytable.c.somearray) == None
+
+ .. versionchanged:: 1.4.26 repaired the use of any_() / all_()
+ comparing to NULL on the right side to be flipped to the left.
+
+ The column-level :meth:`_sql.ColumnElement.any_` method (not to be
+ confused with :class:`_types.ARRAY` level
+ :meth:`_types.ARRAY.Comparator.any`) is shorthand for
+ ``any_(col)``::
+
+ 5 = mytable.c.somearray.any_()
+
+ .. seealso::
+
+ :meth:`_sql.ColumnOperators.any_`
+
+ :func:`_expression.all_`
+
+ """
+ return CollectionAggregate._create_any(expr)
+
+
+def asc(column):
+ """Produce an ascending ``ORDER BY`` clause element.
+
+ e.g.::
+
+ from sqlalchemy import asc
+ stmt = select(users_table).order_by(asc(users_table.c.name))
+
+ will produce SQL as::
+
+ SELECT id, name FROM user ORDER BY name ASC
+
+ The :func:`.asc` function is a standalone version of the
+ :meth:`_expression.ColumnElement.asc`
+ method available on all SQL expressions,
+ e.g.::
+
+
+ stmt = select(users_table).order_by(users_table.c.name.asc())
+
+ :param column: A :class:`_expression.ColumnElement` (e.g.
+ scalar SQL expression)
+ with which to apply the :func:`.asc` operation.
+
+ .. seealso::
+
+ :func:`.desc`
+
+ :func:`.nulls_first`
+
+ :func:`.nulls_last`
+
+ :meth:`_expression.Select.order_by`
+
+ """
+ return UnaryExpression._create_asc(column)
+
+
+def collate(expression, collation):
+ """Return the clause ``expression COLLATE collation``.
+
+ e.g.::
+
+ collate(mycolumn, 'utf8_bin')
+
+ produces::
+
+ mycolumn COLLATE utf8_bin
+
+ The collation expression is also quoted if it is a case sensitive
+ identifier, e.g. contains uppercase characters.
+
+ .. versionchanged:: 1.2 quoting is automatically applied to COLLATE
+ expressions if they are case sensitive.
+
+ """
+ return CollationClause._create_collation_expression(expression, collation)
+
+
+def between(expr, lower_bound, upper_bound, symmetric=False):
+ """Produce a ``BETWEEN`` predicate clause.
+
+ E.g.::
+
+ from sqlalchemy import between
+ stmt = select(users_table).where(between(users_table.c.id, 5, 7))
+
+ Would produce SQL resembling::
+
+ SELECT id, name FROM user WHERE id BETWEEN :id_1 AND :id_2
+
+ The :func:`.between` function is a standalone version of the
+ :meth:`_expression.ColumnElement.between` method available on all
+ SQL expressions, as in::
+
+ stmt = select(users_table).where(users_table.c.id.between(5, 7))
+
+ All arguments passed to :func:`.between`, including the left side
+ column expression, are coerced from Python scalar values if a
+ the value is not a :class:`_expression.ColumnElement` subclass.
+ For example,
+ three fixed values can be compared as in::
+
+ print(between(5, 3, 7))
+
+ Which would produce::
+
+ :param_1 BETWEEN :param_2 AND :param_3
+
+ :param expr: a column expression, typically a
+ :class:`_expression.ColumnElement`
+ instance or alternatively a Python scalar expression to be coerced
+ into a column expression, serving as the left side of the ``BETWEEN``
+ expression.
+
+ :param lower_bound: a column or Python scalar expression serving as the
+ lower bound of the right side of the ``BETWEEN`` expression.
+
+ :param upper_bound: a column or Python scalar expression serving as the
+ upper bound of the right side of the ``BETWEEN`` expression.
+
+ :param symmetric: if True, will render " BETWEEN SYMMETRIC ". Note
+ that not all databases support this syntax.
+
+ .. versionadded:: 0.9.5
+
+ .. seealso::
+
+ :meth:`_expression.ColumnElement.between`
+
+ """
+ expr = coercions.expect(roles.ExpressionElementRole, expr)
+ return expr.between(lower_bound, upper_bound, symmetric=symmetric)
+
+
+def outparam(key, type_=None):
+ """Create an 'OUT' parameter for usage in functions (stored procedures),
+ for databases which support them.
+
+ The ``outparam`` can be used like a regular function parameter.
+ The "output" value will be available from the
+ :class:`~sqlalchemy.engine.CursorResult` object via its ``out_parameters``
+ attribute, which returns a dictionary containing the values.
+
+ """
+ return BindParameter(key, None, type_=type_, unique=False, isoutparam=True)
+
+
+@overload
+def not_(clause: "BinaryExpression[_T]") -> "BinaryExpression[_T]":
+ ...
+
+
+@overload
+def not_(clause: "ColumnElement[_T]") -> "UnaryExpression[_T]":
+ ...
+
+
+def not_(clause: "ColumnElement[_T]") -> "ColumnElement[_T]":
+ """Return a negation of the given clause, i.e. ``NOT(clause)``.
+
+ The ``~`` operator is also overloaded on all
+ :class:`_expression.ColumnElement` subclasses to produce the
+ same result.
+
+ """
+
+ return operators.inv(
+ _typing_cast(
+ "ColumnElement[_T]",
+ coercions.expect(roles.ExpressionElementRole, clause),
+ )
+ )
+
+
+def bindparam(
+ key,
+ value=NO_ARG,
+ type_: Optional[Union[Type["TypeEngine[_T]"], "TypeEngine[_T]"]] = None,
+ unique=False,
+ required=NO_ARG,
+ quote=None,
+ callable_=None,
+ expanding=False,
+ isoutparam=False,
+ literal_execute=False,
+ _compared_to_operator=None,
+ _compared_to_type=None,
+ _is_crud=False,
+) -> "BindParameter[_T]":
+ r"""Produce a "bound expression".
+
+ The return value is an instance of :class:`.BindParameter`; this
+ is a :class:`_expression.ColumnElement`
+ subclass which represents a so-called
+ "placeholder" value in a SQL expression, the value of which is
+ supplied at the point at which the statement in executed against a
+ database connection.
+
+ In SQLAlchemy, the :func:`.bindparam` construct has
+ the ability to carry along the actual value that will be ultimately
+ used at expression time. In this way, it serves not just as
+ a "placeholder" for eventual population, but also as a means of
+ representing so-called "unsafe" values which should not be rendered
+ directly in a SQL statement, but rather should be passed along
+ to the :term:`DBAPI` as values which need to be correctly escaped
+ and potentially handled for type-safety.
+
+ When using :func:`.bindparam` explicitly, the use case is typically
+ one of traditional deferment of parameters; the :func:`.bindparam`
+ construct accepts a name which can then be referred to at execution
+ time::
+
+ from sqlalchemy import bindparam
+
+ stmt = select(users_table).\
+ where(users_table.c.name == bindparam('username'))
+
+ The above statement, when rendered, will produce SQL similar to::
+
+ SELECT id, name FROM user WHERE name = :username
+
+ In order to populate the value of ``:username`` above, the value
+ would typically be applied at execution time to a method
+ like :meth:`_engine.Connection.execute`::
+
+ result = connection.execute(stmt, username='wendy')
+
+ Explicit use of :func:`.bindparam` is also common when producing
+ UPDATE or DELETE statements that are to be invoked multiple times,
+ where the WHERE criterion of the statement is to change on each
+ invocation, such as::
+
+ stmt = (users_table.update().
+ where(user_table.c.name == bindparam('username')).
+ values(fullname=bindparam('fullname'))
+ )
+
+ connection.execute(
+ stmt, [{"username": "wendy", "fullname": "Wendy Smith"},
+ {"username": "jack", "fullname": "Jack Jones"},
+ ]
+ )
+
+ SQLAlchemy's Core expression system makes wide use of
+ :func:`.bindparam` in an implicit sense. It is typical that Python
+ literal values passed to virtually all SQL expression functions are
+ coerced into fixed :func:`.bindparam` constructs. For example, given
+ a comparison operation such as::
+
+ expr = users_table.c.name == 'Wendy'
+
+ The above expression will produce a :class:`.BinaryExpression`
+ construct, where the left side is the :class:`_schema.Column` object
+ representing the ``name`` column, and the right side is a
+ :class:`.BindParameter` representing the literal value::
+
+ print(repr(expr.right))
+ BindParameter('%(4327771088 name)s', 'Wendy', type_=String())
+
+ The expression above will render SQL such as::
+
+ user.name = :name_1
+
+ Where the ``:name_1`` parameter name is an anonymous name. The
+ actual string ``Wendy`` is not in the rendered string, but is carried
+ along where it is later used within statement execution. If we
+ invoke a statement like the following::
+
+ stmt = select(users_table).where(users_table.c.name == 'Wendy')
+ result = connection.execute(stmt)
+
+ We would see SQL logging output as::
+
+ SELECT "user".id, "user".name
+ FROM "user"
+ WHERE "user".name = %(name_1)s
+ {'name_1': 'Wendy'}
+
+ Above, we see that ``Wendy`` is passed as a parameter to the database,
+ while the placeholder ``:name_1`` is rendered in the appropriate form
+ for the target database, in this case the PostgreSQL database.
+
+ Similarly, :func:`.bindparam` is invoked automatically when working
+ with :term:`CRUD` statements as far as the "VALUES" portion is
+ concerned. The :func:`_expression.insert` construct produces an
+ ``INSERT`` expression which will, at statement execution time, generate
+ bound placeholders based on the arguments passed, as in::
+
+ stmt = users_table.insert()
+ result = connection.execute(stmt, name='Wendy')
+
+ The above will produce SQL output as::
+
+ INSERT INTO "user" (name) VALUES (%(name)s)
+ {'name': 'Wendy'}
+
+ The :class:`_expression.Insert` construct, at
+ compilation/execution time, rendered a single :func:`.bindparam`
+ mirroring the column name ``name`` as a result of the single ``name``
+ parameter we passed to the :meth:`_engine.Connection.execute` method.
+
+ :param key:
+ the key (e.g. the name) for this bind param.
+ Will be used in the generated
+ SQL statement for dialects that use named parameters. This
+ value may be modified when part of a compilation operation,
+ if other :class:`BindParameter` objects exist with the same
+ key, or if its length is too long and truncation is
+ required.
+
+ :param value:
+ Initial value for this bind param. Will be used at statement
+ execution time as the value for this parameter passed to the
+ DBAPI, if no other value is indicated to the statement execution
+ method for this particular parameter name. Defaults to ``None``.
+
+ :param callable\_:
+ A callable function that takes the place of "value". The function
+ will be called at statement execution time to determine the
+ ultimate value. Used for scenarios where the actual bind
+ value cannot be determined at the point at which the clause
+ construct is created, but embedded bind values are still desirable.
+
+ :param type\_:
+ A :class:`.TypeEngine` class or instance representing an optional
+ datatype for this :func:`.bindparam`. If not passed, a type
+ may be determined automatically for the bind, based on the given
+ value; for example, trivial Python types such as ``str``,
+ ``int``, ``bool``
+ may result in the :class:`.String`, :class:`.Integer` or
+ :class:`.Boolean` types being automatically selected.
+
+ The type of a :func:`.bindparam` is significant especially in that
+ the type will apply pre-processing to the value before it is
+ passed to the database. For example, a :func:`.bindparam` which
+ refers to a datetime value, and is specified as holding the
+ :class:`.DateTime` type, may apply conversion needed to the
+ value (such as stringification on SQLite) before passing the value
+ to the database.
+
+ :param unique:
+ if True, the key name of this :class:`.BindParameter` will be
+ modified if another :class:`.BindParameter` of the same name
+ already has been located within the containing
+ expression. This flag is used generally by the internals
+ when producing so-called "anonymous" bound expressions, it
+ isn't generally applicable to explicitly-named :func:`.bindparam`
+ constructs.
+
+ :param required:
+ If ``True``, a value is required at execution time. If not passed,
+ it defaults to ``True`` if neither :paramref:`.bindparam.value`
+ or :paramref:`.bindparam.callable` were passed. If either of these
+ parameters are present, then :paramref:`.bindparam.required`
+ defaults to ``False``.
+
+ :param quote:
+ True if this parameter name requires quoting and is not
+ currently known as a SQLAlchemy reserved word; this currently
+ only applies to the Oracle backend, where bound names must
+ sometimes be quoted.
+
+ :param isoutparam:
+ if True, the parameter should be treated like a stored procedure
+ "OUT" parameter. This applies to backends such as Oracle which
+ support OUT parameters.
+
+ :param expanding:
+ if True, this parameter will be treated as an "expanding" parameter
+ at execution time; the parameter value is expected to be a sequence,
+ rather than a scalar value, and the string SQL statement will
+ be transformed on a per-execution basis to accommodate the sequence
+ with a variable number of parameter slots passed to the DBAPI.
+ This is to allow statement caching to be used in conjunction with
+ an IN clause.
+
+ .. seealso::
+
+ :meth:`.ColumnOperators.in_`
+
+ :ref:`baked_in` - with baked queries
+
+ .. note:: The "expanding" feature does not support "executemany"-
+ style parameter sets.
+
+ .. versionadded:: 1.2
+
+ .. versionchanged:: 1.3 the "expanding" bound parameter feature now
+ supports empty lists.
+
+
+ .. seealso::
+
+ :ref:`coretutorial_bind_param`
+
+ :ref:`coretutorial_insert_expressions`
+
+ :func:`.outparam`
+
+ :param literal_execute:
+ if True, the bound parameter will be rendered in the compile phase
+ with a special "POSTCOMPILE" token, and the SQLAlchemy compiler will
+ render the final value of the parameter into the SQL statement at
+ statement execution time, omitting the value from the parameter
+ dictionary / list passed to DBAPI ``cursor.execute()``. This
+ produces a similar effect as that of using the ``literal_binds``,
+ compilation flag, however takes place as the statement is sent to
+ the DBAPI ``cursor.execute()`` method, rather than when the statement
+ is compiled. The primary use of this
+ capability is for rendering LIMIT / OFFSET clauses for database
+ drivers that can't accommodate for bound parameters in these
+ contexts, while allowing SQL constructs to be cacheable at the
+ compilation level.
+
+ .. versionadded:: 1.4 Added "post compile" bound parameters
+
+ .. seealso::
+
+ :ref:`change_4808`.
+
+ """
+ return BindParameter(
+ key,
+ value,
+ type_,
+ unique,
+ required,
+ quote,
+ callable_,
+ expanding,
+ isoutparam,
+ literal_execute,
+ _compared_to_operator,
+ _compared_to_type,
+ _is_crud,
+ )
+
+
+def case(*whens, value=None, else_=None) -> "Case[Any]":
+ r"""Produce a ``CASE`` expression.
+
+ The ``CASE`` construct in SQL is a conditional object that
+ acts somewhat analogously to an "if/then" construct in other
+ languages. It returns an instance of :class:`.Case`.
+
+ :func:`.case` in its usual form is passed a series of "when"
+ constructs, that is, a list of conditions and results as tuples::
+
+ from sqlalchemy import case
+
+ stmt = select(users_table).\
+ where(
+ case(
+ (users_table.c.name == 'wendy', 'W'),
+ (users_table.c.name == 'jack', 'J'),
+ else_='E'
+ )
+ )
+
+ The above statement will produce SQL resembling::
+
+ SELECT id, name FROM user
+ WHERE CASE
+ WHEN (name = :name_1) THEN :param_1
+ WHEN (name = :name_2) THEN :param_2
+ ELSE :param_3
+ END
+
+ When simple equality expressions of several values against a single
+ parent column are needed, :func:`.case` also has a "shorthand" format
+ used via the
+ :paramref:`.case.value` parameter, which is passed a column
+ expression to be compared. In this form, the :paramref:`.case.whens`
+ parameter is passed as a dictionary containing expressions to be
+ compared against keyed to result expressions. The statement below is
+ equivalent to the preceding statement::
+
+ stmt = select(users_table).\
+ where(
+ case(
+ {"wendy": "W", "jack": "J"},
+ value=users_table.c.name,
+ else_='E'
+ )
+ )
+
+ The values which are accepted as result values in
+ :paramref:`.case.whens` as well as with :paramref:`.case.else_` are
+ coerced from Python literals into :func:`.bindparam` constructs.
+ SQL expressions, e.g. :class:`_expression.ColumnElement` constructs,
+ are accepted
+ as well. To coerce a literal string expression into a constant
+ expression rendered inline, use the :func:`_expression.literal_column`
+ construct,
+ as in::
+
+ from sqlalchemy import case, literal_column
+
+ case(
+ (
+ orderline.c.qty > 100,
+ literal_column("'greaterthan100'")
+ ),
+ (
+ orderline.c.qty > 10,
+ literal_column("'greaterthan10'")
+ ),
+ else_=literal_column("'lessthan10'")
+ )
+
+ The above will render the given constants without using bound
+ parameters for the result values (but still for the comparison
+ values), as in::
+
+ CASE
+ WHEN (orderline.qty > :qty_1) THEN 'greaterthan100'
+ WHEN (orderline.qty > :qty_2) THEN 'greaterthan10'
+ ELSE 'lessthan10'
+ END
+
+ :param \*whens: The criteria to be compared against,
+ :paramref:`.case.whens` accepts two different forms, based on
+ whether or not :paramref:`.case.value` is used.
+
+ .. versionchanged:: 1.4 the :func:`_sql.case`
+ function now accepts the series of WHEN conditions positionally
+
+ In the first form, it accepts a list of 2-tuples; each 2-tuple
+ consists of ``(<sql expression>, <value>)``, where the SQL
+ expression is a boolean expression and "value" is a resulting value,
+ e.g.::
+
+ case(
+ (users_table.c.name == 'wendy', 'W'),
+ (users_table.c.name == 'jack', 'J')
+ )
+
+ In the second form, it accepts a Python dictionary of comparison
+ values mapped to a resulting value; this form requires
+ :paramref:`.case.value` to be present, and values will be compared
+ using the ``==`` operator, e.g.::
+
+ case(
+ {"wendy": "W", "jack": "J"},
+ value=users_table.c.name
+ )
+
+ :param value: An optional SQL expression which will be used as a
+ fixed "comparison point" for candidate values within a dictionary
+ passed to :paramref:`.case.whens`.
+
+ :param else\_: An optional SQL expression which will be the evaluated
+ result of the ``CASE`` construct if all expressions within
+ :paramref:`.case.whens` evaluate to false. When omitted, most
+ databases will produce a result of NULL if none of the "when"
+ expressions evaluate to true.
+
+
+ """
+ return Case(*whens, value=value, else_=else_)
+
+
+def cast(
+ expression: ColumnElement,
+ type_: Union[Type["TypeEngine[_T]"], "TypeEngine[_T]"],
+) -> "Cast[_T]":
+ r"""Produce a ``CAST`` expression.
+
+ :func:`.cast` returns an instance of :class:`.Cast`.
+
+ E.g.::
+
+ from sqlalchemy import cast, Numeric
+
+ stmt = select(cast(product_table.c.unit_price, Numeric(10, 4)))
+
+ The above statement will produce SQL resembling::
+
+ SELECT CAST(unit_price AS NUMERIC(10, 4)) FROM product
+
+ The :func:`.cast` function performs two distinct functions when
+ used. The first is that it renders the ``CAST`` expression within
+ the resulting SQL string. The second is that it associates the given
+ type (e.g. :class:`.TypeEngine` class or instance) with the column
+ expression on the Python side, which means the expression will take
+ on the expression operator behavior associated with that type,
+ as well as the bound-value handling and result-row-handling behavior
+ of the type.
+
+ .. versionchanged:: 0.9.0 :func:`.cast` now applies the given type
+ to the expression such that it takes effect on the bound-value,
+ e.g. the Python-to-database direction, in addition to the
+ result handling, e.g. database-to-Python, direction.
+
+ An alternative to :func:`.cast` is the :func:`.type_coerce` function.
+ This function performs the second task of associating an expression
+ with a specific type, but does not render the ``CAST`` expression
+ in SQL.
+
+ :param expression: A SQL expression, such as a
+ :class:`_expression.ColumnElement`
+ expression or a Python string which will be coerced into a bound
+ literal value.
+
+ :param type\_: A :class:`.TypeEngine` class or instance indicating
+ the type to which the ``CAST`` should apply.
+
+ .. seealso::
+
+ :ref:`coretutorial_casts`
+
+ :func:`.type_coerce` - an alternative to CAST that coerces the type
+ on the Python side only, which is often sufficient to generate the
+ correct SQL and data coercion.
+
+
+ """
+ return Cast(expression, type_)
+
+
+def column(
+ text: str,
+ type_: Optional[Union[Type["TypeEngine[_T]"], "TypeEngine[_T]"]] = None,
+ is_literal: bool = False,
+ _selectable: Optional["FromClause"] = None,
+) -> "ColumnClause[_T]":
+ """Produce a :class:`.ColumnClause` object.
+
+ The :class:`.ColumnClause` is a lightweight analogue to the
+ :class:`_schema.Column` class. The :func:`_expression.column`
+ function can
+ be invoked with just a name alone, as in::
+
+ from sqlalchemy import column
+
+ id, name = column("id"), column("name")
+ stmt = select(id, name).select_from("user")
+
+ The above statement would produce SQL like::
+
+ SELECT id, name FROM user
+
+ Once constructed, :func:`_expression.column`
+ may be used like any other SQL
+ expression element such as within :func:`_expression.select`
+ constructs::
+
+ from sqlalchemy.sql import column
+
+ id, name = column("id"), column("name")
+ stmt = select(id, name).select_from("user")
+
+ The text handled by :func:`_expression.column`
+ is assumed to be handled
+ like the name of a database column; if the string contains mixed case,
+ special characters, or matches a known reserved word on the target
+ backend, the column expression will render using the quoting
+ behavior determined by the backend. To produce a textual SQL
+ expression that is rendered exactly without any quoting,
+ use :func:`_expression.literal_column` instead,
+ or pass ``True`` as the
+ value of :paramref:`_expression.column.is_literal`. Additionally,
+ full SQL
+ statements are best handled using the :func:`_expression.text`
+ construct.
+
+ :func:`_expression.column` can be used in a table-like
+ fashion by combining it with the :func:`.table` function
+ (which is the lightweight analogue to :class:`_schema.Table`
+ ) to produce
+ a working table construct with minimal boilerplate::
+
+ from sqlalchemy import table, column, select
+
+ user = table("user",
+ column("id"),
+ column("name"),
+ column("description"),
+ )
+
+ stmt = select(user.c.description).where(user.c.name == 'wendy')
+
+ A :func:`_expression.column` / :func:`.table`
+ construct like that illustrated
+ above can be created in an
+ ad-hoc fashion and is not associated with any
+ :class:`_schema.MetaData`, DDL, or events, unlike its
+ :class:`_schema.Table` counterpart.
+
+ .. versionchanged:: 1.0.0 :func:`_expression.column` can now
+ be imported from the plain ``sqlalchemy`` namespace like any
+ other SQL element.
+
+ :param text: the text of the element.
+
+ :param type: :class:`_types.TypeEngine` object which can associate
+ this :class:`.ColumnClause` with a type.
+
+ :param is_literal: if True, the :class:`.ColumnClause` is assumed to
+ be an exact expression that will be delivered to the output with no
+ quoting rules applied regardless of case sensitive settings. the
+ :func:`_expression.literal_column()` function essentially invokes
+ :func:`_expression.column` while passing ``is_literal=True``.
+
+ .. seealso::
+
+ :class:`_schema.Column`
+
+ :func:`_expression.literal_column`
+
+ :func:`.table`
+
+ :func:`_expression.text`
+
+ :ref:`sqlexpression_literal_column`
+
+ """
+ self = ColumnClause.__new__(ColumnClause)
+ self.__init__(text, type_, is_literal, _selectable)
+ return self
+
+
+def desc(column):
+ """Produce a descending ``ORDER BY`` clause element.
+
+ e.g.::
+
+ from sqlalchemy import desc
+
+ stmt = select(users_table).order_by(desc(users_table.c.name))
+
+ will produce SQL as::
+
+ SELECT id, name FROM user ORDER BY name DESC
+
+ The :func:`.desc` function is a standalone version of the
+ :meth:`_expression.ColumnElement.desc`
+ method available on all SQL expressions,
+ e.g.::
+
+
+ stmt = select(users_table).order_by(users_table.c.name.desc())
+
+ :param column: A :class:`_expression.ColumnElement` (e.g.
+ scalar SQL expression)
+ with which to apply the :func:`.desc` operation.
+
+ .. seealso::
+
+ :func:`.asc`
+
+ :func:`.nulls_first`
+
+ :func:`.nulls_last`
+
+ :meth:`_expression.Select.order_by`
+
+ """
+ return UnaryExpression._create_desc(column)
+
+
+def distinct(expr):
+ """Produce an column-expression-level unary ``DISTINCT`` clause.
+
+ This applies the ``DISTINCT`` keyword to an individual column
+ expression, and is typically contained within an aggregate function,
+ as in::
+
+ from sqlalchemy import distinct, func
+ stmt = select(func.count(distinct(users_table.c.name)))
+
+ The above would produce an expression resembling::
+
+ SELECT COUNT(DISTINCT name) FROM user
+
+ The :func:`.distinct` function is also available as a column-level
+ method, e.g. :meth:`_expression.ColumnElement.distinct`, as in::
+
+ stmt = select(func.count(users_table.c.name.distinct()))
+
+ The :func:`.distinct` operator is different from the
+ :meth:`_expression.Select.distinct` method of
+ :class:`_expression.Select`,
+ which produces a ``SELECT`` statement
+ with ``DISTINCT`` applied to the result set as a whole,
+ e.g. a ``SELECT DISTINCT`` expression. See that method for further
+ information.
+
+ .. seealso::
+
+ :meth:`_expression.ColumnElement.distinct`
+
+ :meth:`_expression.Select.distinct`
+
+ :data:`.func`
+
+ """
+ return UnaryExpression._create_distinct(expr)
+
+
+def extract(field: str, expr: ColumnElement) -> "Extract[sqltypes.Integer]":
+ """Return a :class:`.Extract` construct.
+
+ This is typically available as :func:`.extract`
+ as well as ``func.extract`` from the
+ :data:`.func` namespace.
+
+ :param field: The field to extract.
+
+ :param expr: A column or Python scalar expression serving as the
+ right side of the ``EXTRACT`` expression.
+
+ E.g.::
+
+ from sqlalchemy import extract
+ from sqlalchemy import table, column
+
+ logged_table = table("user",
+ column("id"),
+ column("date_created"),
+ )
+
+ stmt = select(logged_table.c.id).where(
+ extract("YEAR", logged_table.c.date_created) == 2021
+ )
+
+ In the above example, the statement is used to select ids from the
+ database where the ``YEAR`` component matches a specific value.
+
+ Similarly, one can also select an extracted component::
+
+ stmt = select(
+ extract("YEAR", logged_table.c.date_created)
+ ).where(logged_table.c.id == 1)
+
+ The implementation of ``EXTRACT`` may vary across database backends.
+ Users are reminded to consult their database documentation.
+ """
+ return Extract(field, expr)
+
+
+def false():
+ """Return a :class:`.False_` construct.
+
+ E.g.::
+
+ >>> from sqlalchemy import false
+ >>> print(select(t.c.x).where(false()))
+ SELECT x FROM t WHERE false
+
+ A backend which does not support true/false constants will render as
+ an expression against 1 or 0::
+
+ >>> print(select(t.c.x).where(false()))
+ SELECT x FROM t WHERE 0 = 1
+
+ The :func:`.true` and :func:`.false` constants also feature
+ "short circuit" operation within an :func:`.and_` or :func:`.or_`
+ conjunction::
+
+ >>> print(select(t.c.x).where(or_(t.c.x > 5, true())))
+ SELECT x FROM t WHERE true
+
+ >>> print(select(t.c.x).where(and_(t.c.x > 5, false())))
+ SELECT x FROM t WHERE false
+
+ .. versionchanged:: 0.9 :func:`.true` and :func:`.false` feature
+ better integrated behavior within conjunctions and on dialects
+ that don't support true/false constants.
+
+ .. seealso::
+
+ :func:`.true`
+
+ """
+
+ return False_._instance()
+
+
+def funcfilter(func, *criterion) -> "FunctionFilter":
+ """Produce a :class:`.FunctionFilter` object against a function.
+
+ Used against aggregate and window functions,
+ for database backends that support the "FILTER" clause.
+
+ E.g.::
+
+ from sqlalchemy import funcfilter
+ funcfilter(func.count(1), MyClass.name == 'some name')
+
+ Would produce "COUNT(1) FILTER (WHERE myclass.name = 'some name')".
+
+ This function is also available from the :data:`~.expression.func`
+ construct itself via the :meth:`.FunctionElement.filter` method.
+
+ .. versionadded:: 1.0.0
+
+ .. seealso::
+
+ :ref:`tutorial_functions_within_group` - in the
+ :ref:`unified_tutorial`
+
+ :meth:`.FunctionElement.filter`
+
+ """
+ return FunctionFilter(func, *criterion)
+
+
+def label(
+ name: str,
+ element: ColumnElement[_T],
+ type_: Optional[Union[Type["TypeEngine[_T]"], "TypeEngine[_T]"]] = None,
+) -> "Label[_T]":
+ """Return a :class:`Label` object for the
+ given :class:`_expression.ColumnElement`.
+
+ A label changes the name of an element in the columns clause of a
+ ``SELECT`` statement, typically via the ``AS`` SQL keyword.
+
+ This functionality is more conveniently available via the
+ :meth:`_expression.ColumnElement.label` method on
+ :class:`_expression.ColumnElement`.
+
+ :param name: label name
+
+ :param obj: a :class:`_expression.ColumnElement`.
+
+ """
+ return Label(name, element, type_)
+
+
+def null():
+ """Return a constant :class:`.Null` construct."""
+
+ return Null._instance()
+
+
+def nulls_first(column):
+ """Produce the ``NULLS FIRST`` modifier for an ``ORDER BY`` expression.
+
+ :func:`.nulls_first` is intended to modify the expression produced
+ by :func:`.asc` or :func:`.desc`, and indicates how NULL values
+ should be handled when they are encountered during ordering::
+
+
+ from sqlalchemy import desc, nulls_first
+
+ stmt = select(users_table).order_by(
+ nulls_first(desc(users_table.c.name)))
+
+ The SQL expression from the above would resemble::
+
+ SELECT id, name FROM user ORDER BY name DESC NULLS FIRST
+
+ Like :func:`.asc` and :func:`.desc`, :func:`.nulls_first` is typically
+ invoked from the column expression itself using
+ :meth:`_expression.ColumnElement.nulls_first`,
+ rather than as its standalone
+ function version, as in::
+
+ stmt = select(users_table).order_by(
+ users_table.c.name.desc().nulls_first())
+
+ .. versionchanged:: 1.4 :func:`.nulls_first` is renamed from
+ :func:`.nullsfirst` in previous releases.
+ The previous name remains available for backwards compatibility.
+
+ .. seealso::
+
+ :func:`.asc`
+
+ :func:`.desc`
+
+ :func:`.nulls_last`
+
+ :meth:`_expression.Select.order_by`
+
+ """
+ return UnaryExpression._create_nulls_first(column)
+
+
+def nulls_last(column):
+ """Produce the ``NULLS LAST`` modifier for an ``ORDER BY`` expression.
+
+ :func:`.nulls_last` is intended to modify the expression produced
+ by :func:`.asc` or :func:`.desc`, and indicates how NULL values
+ should be handled when they are encountered during ordering::
+
+
+ from sqlalchemy import desc, nulls_last
+
+ stmt = select(users_table).order_by(
+ nulls_last(desc(users_table.c.name)))
+
+ The SQL expression from the above would resemble::
+
+ SELECT id, name FROM user ORDER BY name DESC NULLS LAST
+
+ Like :func:`.asc` and :func:`.desc`, :func:`.nulls_last` is typically
+ invoked from the column expression itself using
+ :meth:`_expression.ColumnElement.nulls_last`,
+ rather than as its standalone
+ function version, as in::
+
+ stmt = select(users_table).order_by(
+ users_table.c.name.desc().nulls_last())
+
+ .. versionchanged:: 1.4 :func:`.nulls_last` is renamed from
+ :func:`.nullslast` in previous releases.
+ The previous name remains available for backwards compatibility.
+
+ .. seealso::
+
+ :func:`.asc`
+
+ :func:`.desc`
+
+ :func:`.nulls_first`
+
+ :meth:`_expression.Select.order_by`
+
+ """
+ return UnaryExpression._create_nulls_last(column)
+
+
+def or_(*clauses):
+ """Produce a conjunction of expressions joined by ``OR``.
+
+ E.g.::
+
+ from sqlalchemy import or_
+
+ stmt = select(users_table).where(
+ or_(
+ users_table.c.name == 'wendy',
+ users_table.c.name == 'jack'
+ )
+ )
+
+ The :func:`.or_` conjunction is also available using the
+ Python ``|`` operator (though note that compound expressions
+ need to be parenthesized in order to function with Python
+ operator precedence behavior)::
+
+ stmt = select(users_table).where(
+ (users_table.c.name == 'wendy') |
+ (users_table.c.name == 'jack')
+ )
+
+ The :func:`.or_` construct must be given at least one positional
+ argument in order to be valid; a :func:`.or_` construct with no
+ arguments is ambiguous. To produce an "empty" or dynamically
+ generated :func:`.or_` expression, from a given list of expressions,
+ a "default" element of ``False`` should be specified::
+
+ or_criteria = or_(False, *expressions)
+
+ The above expression will compile to SQL as the expression ``false``
+ or ``0 = 1``, depending on backend, if no other expressions are
+ present. If expressions are present, then the ``False`` value is
+ ignored as it does not affect the outcome of an OR expression which
+ has other elements.
+
+ .. deprecated:: 1.4 The :func:`.or_` element now requires that at
+ least one argument is passed; creating the :func:`.or_` construct
+ with no arguments is deprecated, and will emit a deprecation warning
+ while continuing to produce a blank SQL string.
+
+ .. seealso::
+
+ :func:`.and_`
+
+ """
+ return BooleanClauseList.or_(*clauses)
+
+
+def over(
+ element: "FunctionElement[_T]",
+ partition_by=None,
+ order_by=None,
+ range_=None,
+ rows=None,
+) -> "Over[_T]":
+ r"""Produce an :class:`.Over` object against a function.
+
+ Used against aggregate or so-called "window" functions,
+ for database backends that support window functions.
+
+ :func:`_expression.over` is usually called using
+ the :meth:`.FunctionElement.over` method, e.g.::
+
+ func.row_number().over(order_by=mytable.c.some_column)
+
+ Would produce::
+
+ ROW_NUMBER() OVER(ORDER BY some_column)
+
+ Ranges are also possible using the :paramref:`.expression.over.range_`
+ and :paramref:`.expression.over.rows` parameters. These
+ mutually-exclusive parameters each accept a 2-tuple, which contains
+ a combination of integers and None::
+
+ func.row_number().over(
+ order_by=my_table.c.some_column, range_=(None, 0))
+
+ The above would produce::
+
+ ROW_NUMBER() OVER(ORDER BY some_column
+ RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)
+
+ A value of ``None`` indicates "unbounded", a
+ value of zero indicates "current row", and negative / positive
+ integers indicate "preceding" and "following":
+
+ * RANGE BETWEEN 5 PRECEDING AND 10 FOLLOWING::
+
+ func.row_number().over(order_by='x', range_=(-5, 10))
+
+ * ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW::
+
+ func.row_number().over(order_by='x', rows=(None, 0))
+
+ * RANGE BETWEEN 2 PRECEDING AND UNBOUNDED FOLLOWING::
+
+ func.row_number().over(order_by='x', range_=(-2, None))
+
+ * RANGE BETWEEN 1 FOLLOWING AND 3 FOLLOWING::
+
+ func.row_number().over(order_by='x', range_=(1, 3))
+
+ .. versionadded:: 1.1 support for RANGE / ROWS within a window
+
+
+ :param element: a :class:`.FunctionElement`, :class:`.WithinGroup`,
+ or other compatible construct.
+ :param partition_by: a column element or string, or a list
+ of such, that will be used as the PARTITION BY clause
+ of the OVER construct.
+ :param order_by: a column element or string, or a list
+ of such, that will be used as the ORDER BY clause
+ of the OVER construct.
+ :param range\_: optional range clause for the window. This is a
+ tuple value which can contain integer values or ``None``,
+ and will render a RANGE BETWEEN PRECEDING / FOLLOWING clause.
+
+ .. versionadded:: 1.1
+
+ :param rows: optional rows clause for the window. This is a tuple
+ value which can contain integer values or None, and will render
+ a ROWS BETWEEN PRECEDING / FOLLOWING clause.
+
+ .. versionadded:: 1.1
+
+ This function is also available from the :data:`~.expression.func`
+ construct itself via the :meth:`.FunctionElement.over` method.
+
+ .. seealso::
+
+ :ref:`tutorial_window_functions` - in the :ref:`unified_tutorial`
+
+ :data:`.expression.func`
+
+ :func:`_expression.within_group`
+
+ """
+ return Over(element, partition_by, order_by, range_, rows)
+
+
+@_document_text_coercion("text", ":func:`.text`", ":paramref:`.text.text`")
+def text(text):
+ r"""Construct a new :class:`_expression.TextClause` clause,
+ representing
+ a textual SQL string directly.
+
+ E.g.::
+
+ from sqlalchemy import text
+
+ t = text("SELECT * FROM users")
+ result = connection.execute(t)
+
+ The advantages :func:`_expression.text`
+ provides over a plain string are
+ backend-neutral support for bind parameters, per-statement
+ execution options, as well as
+ bind parameter and result-column typing behavior, allowing
+ SQLAlchemy type constructs to play a role when executing
+ a statement that is specified literally. The construct can also
+ be provided with a ``.c`` collection of column elements, allowing
+ it to be embedded in other SQL expression constructs as a subquery.
+
+ Bind parameters are specified by name, using the format ``:name``.
+ E.g.::
+
+ t = text("SELECT * FROM users WHERE id=:user_id")
+ result = connection.execute(t, user_id=12)
+
+ For SQL statements where a colon is required verbatim, as within
+ an inline string, use a backslash to escape::
+
+ t = text("SELECT * FROM users WHERE name='\:username'")
+
+ The :class:`_expression.TextClause`
+ construct includes methods which can
+ provide information about the bound parameters as well as the column
+ values which would be returned from the textual statement, assuming
+ it's an executable SELECT type of statement. The
+ :meth:`_expression.TextClause.bindparams`
+ method is used to provide bound
+ parameter detail, and :meth:`_expression.TextClause.columns`
+ method allows
+ specification of return columns including names and types::
+
+ t = text("SELECT * FROM users WHERE id=:user_id").\
+ bindparams(user_id=7).\
+ columns(id=Integer, name=String)
+
+ for id, name in connection.execute(t):
+ print(id, name)
+
+ The :func:`_expression.text` construct is used in cases when
+ a literal string SQL fragment is specified as part of a larger query,
+ such as for the WHERE clause of a SELECT statement::
+
+ s = select(users.c.id, users.c.name).where(text("id=:user_id"))
+ result = connection.execute(s, user_id=12)
+
+ :func:`_expression.text` is also used for the construction
+ of a full, standalone statement using plain text.
+ As such, SQLAlchemy refers
+ to it as an :class:`.Executable` object and may be used
+ like any other statement passed to an ``.execute()`` method.
+
+ :param text:
+ the text of the SQL statement to be created. Use ``:<param>``
+ to specify bind parameters; they will be compiled to their
+ engine-specific format.
+
+ .. seealso::
+
+ :ref:`sqlexpression_text` - in the Core tutorial
+
+
+ """
+ return TextClause(text)
+
+
+def true():
+ """Return a constant :class:`.True_` construct.
+
+ E.g.::
+
+ >>> from sqlalchemy import true
+ >>> print(select(t.c.x).where(true()))
+ SELECT x FROM t WHERE true
+
+ A backend which does not support true/false constants will render as
+ an expression against 1 or 0::
+
+ >>> print(select(t.c.x).where(true()))
+ SELECT x FROM t WHERE 1 = 1
+
+ The :func:`.true` and :func:`.false` constants also feature
+ "short circuit" operation within an :func:`.and_` or :func:`.or_`
+ conjunction::
+
+ >>> print(select(t.c.x).where(or_(t.c.x > 5, true())))
+ SELECT x FROM t WHERE true
+
+ >>> print(select(t.c.x).where(and_(t.c.x > 5, false())))
+ SELECT x FROM t WHERE false
+
+ .. versionchanged:: 0.9 :func:`.true` and :func:`.false` feature
+ better integrated behavior within conjunctions and on dialects
+ that don't support true/false constants.
+
+ .. seealso::
+
+ :func:`.false`
+
+ """
+
+ return True_._instance()
+
+
+def tuple_(*clauses: roles.ExpressionElementRole, types=None) -> "Tuple":
+ """Return a :class:`.Tuple`.
+
+ Main usage is to produce a composite IN construct using
+ :meth:`.ColumnOperators.in_` ::
+
+ from sqlalchemy import tuple_
+
+ tuple_(table.c.col1, table.c.col2).in_(
+ [(1, 2), (5, 12), (10, 19)]
+ )
+
+ .. versionchanged:: 1.3.6 Added support for SQLite IN tuples.
+
+ .. warning::
+
+ The composite IN construct is not supported by all backends, and is
+ currently known to work on PostgreSQL, MySQL, and SQLite.
+ Unsupported backends will raise a subclass of
+ :class:`~sqlalchemy.exc.DBAPIError` when such an expression is
+ invoked.
+
+ """
+ return Tuple(*clauses, types=types)
+
+
+def type_coerce(
+ expression: "ColumnElement",
+ type_: Union[Type["TypeEngine[_T]"], "TypeEngine[_T]"],
+) -> "TypeCoerce[_T]":
+ r"""Associate a SQL expression with a particular type, without rendering
+ ``CAST``.
+
+ E.g.::
+
+ from sqlalchemy import type_coerce
+
+ stmt = select(type_coerce(log_table.date_string, StringDateTime()))
+
+ The above construct will produce a :class:`.TypeCoerce` object, which
+ does not modify the rendering in any way on the SQL side, with the
+ possible exception of a generated label if used in a columns clause
+ context::
+
+ SELECT date_string AS date_string FROM log
+
+ When result rows are fetched, the ``StringDateTime`` type processor
+ will be applied to result rows on behalf of the ``date_string`` column.
+
+ .. note:: the :func:`.type_coerce` construct does not render any
+ SQL syntax of its own, including that it does not imply
+ parenthesization. Please use :meth:`.TypeCoerce.self_group`
+ if explicit parenthesization is required.
+
+ In order to provide a named label for the expression, use
+ :meth:`_expression.ColumnElement.label`::
+
+ stmt = select(
+ type_coerce(log_table.date_string, StringDateTime()).label('date')
+ )
+
+
+ A type that features bound-value handling will also have that behavior
+ take effect when literal values or :func:`.bindparam` constructs are
+ passed to :func:`.type_coerce` as targets.
+ For example, if a type implements the
+ :meth:`.TypeEngine.bind_expression`
+ method or :meth:`.TypeEngine.bind_processor` method or equivalent,
+ these functions will take effect at statement compilation/execution
+ time when a literal value is passed, as in::
+
+ # bound-value handling of MyStringType will be applied to the
+ # literal value "some string"
+ stmt = select(type_coerce("some string", MyStringType))
+
+ When using :func:`.type_coerce` with composed expressions, note that
+ **parenthesis are not applied**. If :func:`.type_coerce` is being
+ used in an operator context where the parenthesis normally present from
+ CAST are necessary, use the :meth:`.TypeCoerce.self_group` method::
+
+ >>> some_integer = column("someint", Integer)
+ >>> some_string = column("somestr", String)
+ >>> expr = type_coerce(some_integer + 5, String) + some_string
+ >>> print(expr)
+ someint + :someint_1 || somestr
+ >>> expr = type_coerce(some_integer + 5, String).self_group() + some_string
+ >>> print(expr)
+ (someint + :someint_1) || somestr
+
+ :param expression: A SQL expression, such as a
+ :class:`_expression.ColumnElement`
+ expression or a Python string which will be coerced into a bound
+ literal value.
+
+ :param type\_: A :class:`.TypeEngine` class or instance indicating
+ the type to which the expression is coerced.
+
+ .. seealso::
+
+ :ref:`coretutorial_casts`
+
+ :func:`.cast`
+
+ """ # noqa
+ return TypeCoerce(expression, type_)
+
+
+def within_group(
+ element: "FunctionElement[_T]", *order_by: roles.OrderByRole
+) -> "WithinGroup[_T]":
+ r"""Produce a :class:`.WithinGroup` object against a function.
+
+ Used against so-called "ordered set aggregate" and "hypothetical
+ set aggregate" functions, including :class:`.percentile_cont`,
+ :class:`.rank`, :class:`.dense_rank`, etc.
+
+ :func:`_expression.within_group` is usually called using
+ the :meth:`.FunctionElement.within_group` method, e.g.::
+
+ from sqlalchemy import within_group
+ stmt = select(
+ department.c.id,
+ func.percentile_cont(0.5).within_group(
+ department.c.salary.desc()
+ )
+ )
+
+ The above statement would produce SQL similar to
+ ``SELECT department.id, percentile_cont(0.5)
+ WITHIN GROUP (ORDER BY department.salary DESC)``.
+
+ :param element: a :class:`.FunctionElement` construct, typically
+ generated by :data:`~.expression.func`.
+ :param \*order_by: one or more column elements that will be used
+ as the ORDER BY clause of the WITHIN GROUP construct.
+
+ .. versionadded:: 1.1
+
+ .. seealso::
+
+ :ref:`tutorial_functions_within_group` - in the
+ :ref:`unified_tutorial`
+
+ :data:`.expression.func`
+
+ :func:`_expression.over`
+
+ """
+ return WithinGroup(element, *order_by)
--- /dev/null
+# sql/_selectable_constructors.py
+# Copyright (C) 2005-2022 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
+from typing import Union
+
+from . import coercions
+from . import roles
+from .elements import ColumnClause
+from .selectable import Alias
+from .selectable import CompoundSelect
+from .selectable import Exists
+from .selectable import Join
+from .selectable import Lateral
+from .selectable import Select
+from .selectable import TableClause
+from .selectable import TableSample
+from .selectable import Values
+
+
+def alias(selectable, name=None, flat=False):
+ """Return an :class:`_expression.Alias` object.
+
+ An :class:`_expression.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``.
+
+ Similar functionality is available via the
+ :meth:`_expression.FromClause.alias`
+ method available on all :class:`_expression.FromClause` subclasses.
+ In terms of
+ a SELECT object as generated from the :func:`_expression.select`
+ function, the :meth:`_expression.SelectBase.alias` method returns an
+ :class:`_expression.Alias` or similar object which represents a named,
+ parenthesized subquery.
+
+ When an :class:`_expression.Alias` is created from a
+ :class:`_schema.Table` object,
+ this has the effect of the table being rendered
+ as ``tablename AS aliasname`` in a SELECT statement.
+
+ For :func:`_expression.select` objects, the effect is that of
+ creating a named subquery, i.e. ``(select ...) AS aliasname``.
+
+ The ``name`` parameter is optional, and provides the name
+ to use in the rendered SQL. If blank, an "anonymous" 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 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.
+
+ :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, name=None, recursive=False):
+ 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
+ )
+
+
+def except_(*selects):
+ 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)
+
+
+def except_all(*selects):
+ 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=None):
+ """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::
+
+ 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)
+
+
+def intersect(*selects):
+ 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)
+
+
+def intersect_all(*selects):
+ 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, right, onclause=None, isouter=False, full=False):
+ """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::
+
+ 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.
+
+ .. versionadded:: 1.1
+
+ .. seealso::
+
+ :meth:`_expression.FromClause.join` - method form,
+ based on a given left side.
+
+ :class:`_expression.Join` - the type of object produced.
+
+ """
+
+ return Join(left, right, onclause, isouter, full)
+
+
+def lateral(selectable, name=None):
+ """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.
+
+ .. versionadded:: 1.1
+
+ .. seealso::
+
+ :ref:`lateral_selects` - overview of usage.
+
+ """
+ return Lateral._factory(selectable, name=name)
+
+
+def outerjoin(left, right, onclause=None, full=False):
+ """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)
+
+
+def select(*entities: Union[roles.ColumnsClauseRole, Type]) -> "Select":
+ 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:`_future.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:`coretutorial_selecting` - Core Tutorial description of
+ :func:`_expression.select`.
+
+ :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.
+
+ """
+
+ return Select(*entities)
+
+
+def table(name: str, *columns: ColumnClause, **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.
+
+ .. versionchanged:: 1.0.0 :func:`_expression.table` can now
+ be imported from the plain ``sqlalchemy`` namespace like any
+ other SQL element.
+
+
+ :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, sampling, name=None, seed=None):
+ """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::
+
+ SELECT alias.people_id FROM
+ people AS alias TABLESAMPLE bernoulli(:bernoulli_1)
+ REPEATABLE (random())
+
+ .. versionadded:: 1.1
+
+ :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)
+
+
+def union(*selects, **kwargs):
+ 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, **kwargs)
+
+
+def union_all(*selects):
+ 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, name=None, literal_binds=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
+
+ 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)
import collections.abc as collections_abc
import numbers
import re
+import typing
+from typing import Any
+from typing import Callable
+from typing import Optional
+from typing import overload
+from typing import Type
+from typing import TypeVar
+from typing import Union
from . import operators
from . import roles
from .. import inspection
from .. import util
+if not typing.TYPE_CHECKING:
+ elements = None
+ lambdas = None
+ schema = None
+ selectable = None
+ traversals = None
-elements = None
-lambdas = None
-schema = None
-selectable = None
-sqltypes = None
-traversals = None
+if typing.TYPE_CHECKING:
+ from . import elements
+ from . import lambdas
+ from . import schema
+ from . import selectable
+ from . import traversals
+ from .elements import ClauseElement
+ from .elements import ColumnElement
+
+_SR = TypeVar("_SR", bound=roles.SQLRole)
+_StringOnlyR = TypeVar("_StringOnlyR", bound=roles.StringRole)
def _is_literal(element):
return args
+@overload
def expect(
- role,
- element,
- apply_propagate_attrs=None,
- argname=None,
- post_inspect=False,
- **kw,
-):
+ role: Type[roles.InElementRole],
+ element: Any,
+ *,
+ apply_propagate_attrs: Optional["ClauseElement"] = None,
+ argname: Optional[str] = None,
+ post_inspect: bool = False,
+ **kw: Any,
+) -> Union["elements.ColumnElement", "selectable.Select"]:
+ ...
+
+
+@overload
+def expect(
+ role: Type[roles.HasCTERole],
+ element: Any,
+ *,
+ apply_propagate_attrs: Optional["ClauseElement"] = None,
+ argname: Optional[str] = None,
+ post_inspect: bool = False,
+ **kw: Any,
+) -> "selectable.HasCTE":
+ ...
+
+
+@overload
+def expect(
+ role: Type[roles.ExpressionElementRole],
+ element: Any,
+ *,
+ apply_propagate_attrs: Optional["ClauseElement"] = None,
+ argname: Optional[str] = None,
+ post_inspect: bool = False,
+ **kw: Any,
+) -> "ColumnElement":
+ ...
+
+
+@overload
+def expect(
+ role: "Type[_StringOnlyR]",
+ element: Any,
+ *,
+ apply_propagate_attrs: Optional["ClauseElement"] = None,
+ argname: Optional[str] = None,
+ post_inspect: bool = False,
+ **kw: Any,
+) -> str:
+ ...
+
+
+@overload
+def expect(
+ role: Type[_SR],
+ element: Any,
+ *,
+ apply_propagate_attrs: Optional["ClauseElement"] = None,
+ argname: Optional[str] = None,
+ post_inspect: bool = False,
+ **kw: Any,
+) -> _SR:
+ ...
+
+
+@overload
+def expect(
+ role: Type[_SR],
+ element: Callable[..., Any],
+ *,
+ apply_propagate_attrs: Optional["ClauseElement"] = None,
+ argname: Optional[str] = None,
+ post_inspect: bool = False,
+ **kw: Any,
+) -> "lambdas.LambdaElement":
+ ...
+
+
+def expect(
+ role: Type[_SR],
+ element: Any,
+ *,
+ apply_propagate_attrs: Optional["ClauseElement"] = None,
+ argname: Optional[str] = None,
+ post_inspect: bool = False,
+ **kw: Any,
+) -> Union[str, _SR, "lambdas.LambdaElement"]:
if (
role.allows_lambda
# note callable() will not invoke a __getattr__() method, whereas
"""Default implementation of SQL comparison operations.
"""
+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 .elements import and_
from .elements import BinaryExpression
from .elements import ClauseList
-from .elements import collate
+from .elements import CollationClause
from .elements import CollectionAggregate
from .elements import False_
from .elements import Null
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 .sqltypes import TypeEngine
+
def _boolean_compare(
- expr,
- op,
- obj,
- negate=None,
- reverse=False,
+ expr: "ColumnElement",
+ op: OperatorType,
+ obj: roles.BinaryElementRole,
+ *,
+ negate_op: Optional[OperatorType] = None,
+ reverse: bool = False,
_python_is_types=(util.NoneType, bool),
_any_all_expr=False,
- result_type=None,
- **kwargs,
-):
+ result_type: Optional[
+ Union[Type["TypeEngine[bool]"], "TypeEngine[bool]"]
+ ] = None,
+ **kwargs: Any,
+) -> BinaryExpression[bool]:
if result_type is None:
result_type = type_api.BOOLEANTYPE
coercions.expect(roles.ConstExprRole, obj),
op,
type_=result_type,
- negate=negate,
+ negate=negate_op,
modifiers=kwargs,
)
elif op in (
coercions.expect(roles.ConstExprRole, obj),
op,
type_=result_type,
- negate=negate,
+ negate=negate_op,
modifiers=kwargs,
)
elif _any_all_expr:
if reverse:
return BinaryExpression(
- obj, expr, op, type_=result_type, negate=negate, modifiers=kwargs
+ obj,
+ expr,
+ op,
+ type_=result_type,
+ negate=negate_op,
+ modifiers=kwargs,
)
else:
return BinaryExpression(
- expr, obj, op, type_=result_type, negate=negate, modifiers=kwargs
+ expr,
+ obj,
+ op,
+ type_=result_type,
+ negate=negate_op,
+ modifiers=kwargs,
)
)
-def _binary_operate(expr, op, obj, reverse=False, result_type=None, **kw):
- obj = coercions.expect(
+def _binary_operate(
+ expr: "ColumnElement",
+ op: OperatorType,
+ obj: roles.BinaryElementRole,
+ *,
+ reverse=False,
+ result_type: Optional[
+ Union[Type["TypeEngine[_T]"], "TypeEngine[_T]"]
+ ] = None,
+ **kw: Any,
+) -> BinaryExpression[_T]:
+
+ coerced_obj = coercions.expect(
roles.BinaryElementRole, obj, expr=expr, operator=op
)
if reverse:
- left, right = obj, expr
+ left, right = coerced_obj, expr
else:
- left, right = expr, obj
+ left, right = expr, coerced_obj
if result_type is None:
op, result_type = left.comparator._adapt_expression(
return BinaryExpression(left, right, op, type_=result_type, modifiers=kw)
-def _conjunction_operate(expr, op, other, **kw):
+def _conjunction_operate(expr, op, other, **kw) -> "ColumnElement":
if op is operators.and_:
return and_(expr, other)
elif op is operators.or_:
raise NotImplementedError()
-def _scalar(expr, op, fn, **kw):
+def _scalar(expr, op, fn, **kw) -> "ColumnElement":
return fn(expr)
-def _in_impl(expr, op, seq_or_selectable, negate_op, **kw):
+def _in_impl(expr, op, seq_or_selectable, negate_op, **kw) -> "ColumnElement":
seq_or_selectable = coercions.expect(
roles.InElementRole, seq_or_selectable, expr=expr, operator=op
)
op, negate_op = seq_or_selectable._annotations["in_ops"]
return _boolean_compare(
- expr, op, seq_or_selectable, negate=negate_op, **kw
+ expr, op, seq_or_selectable, negate_op=negate_op, **kw
)
-def _getitem_impl(expr, op, other, **kw):
+def _getitem_impl(expr, op, other, **kw) -> "ColumnElement":
if isinstance(expr.type, type_api.INDEXABLE):
other = coercions.expect(
roles.BinaryElementRole, other, expr=expr, operator=op
_unsupported_impl(expr, op, other, **kw)
-def _unsupported_impl(expr, op, *arg, **kw):
+def _unsupported_impl(expr, op, *arg, **kw) -> NoReturn:
raise NotImplementedError(
"Operator '%s' is not supported on " "this expression" % op.__name__
)
-def _inv_impl(expr, op, **kw):
+def _inv_impl(expr, op, **kw) -> "ColumnElement":
"""See :meth:`.ColumnOperators.__inv__`."""
# undocumented element currently used by the ORM for
return expr._negate()
-def _neg_impl(expr, op, **kw):
+def _neg_impl(expr, op, **kw) -> "ColumnElement":
"""See :meth:`.ColumnOperators.__neg__`."""
return UnaryExpression(expr, operator=operators.neg, type_=expr.type)
-def _match_impl(expr, op, other, **kw):
+def _match_impl(expr, op, other, **kw) -> "ColumnElement":
"""See :meth:`.ColumnOperators.match`."""
return _boolean_compare(
operator=operators.match_op,
),
result_type=type_api.MATCHTYPE,
- negate=operators.not_match_op
+ negate_op=operators.not_match_op
if op is operators.match_op
else operators.match_op,
**kw,
)
-def _distinct_impl(expr, op, **kw):
+def _distinct_impl(expr, op, **kw) -> "ColumnElement":
"""See :meth:`.ColumnOperators.distinct`."""
return UnaryExpression(
expr, operator=operators.distinct_op, type_=expr.type
)
-def _between_impl(expr, op, cleft, cright, **kw):
+def _between_impl(expr, op, cleft, cright, **kw) -> "ColumnElement":
"""See :meth:`.ColumnOperators.between`."""
return BinaryExpression(
expr,
)
-def _collate_impl(expr, op, other, **kw):
- return collate(expr, other)
+def _collate_impl(expr, op, collation, **kw) -> "ColumnElement":
+ return CollationClause._create_collation_expression(expr, collation)
-def _regexp_match_impl(expr, op, pattern, flags, **kw):
+def _regexp_match_impl(expr, op, pattern, flags, **kw) -> "ColumnElement":
if flags is not None:
flags = coercions.expect(
roles.BinaryElementRole,
op,
pattern,
flags=flags,
- negate=operators.not_regexp_match_op
+ negate_op=operators.not_regexp_match_op
if op is operators.regexp_match_op
else operators.regexp_match_op,
**kw,
)
-def _regexp_replace_impl(expr, op, pattern, replacement, flags, **kw):
+def _regexp_replace_impl(
+ expr, op, pattern, replacement, flags, **kw
+) -> "ColumnElement":
replacement = coercions.expect(
roles.BinaryElementRole,
replacement,
# a mapping of operators with the method they use, along with
-# their negated operator for comparison operators
-operator_lookup = {
- "and_": (_conjunction_operate,),
- "or_": (_conjunction_operate,),
- "inv": (_inv_impl,),
- "add": (_binary_operate,),
- "mul": (_binary_operate,),
- "sub": (_binary_operate,),
- "div": (_binary_operate,),
- "mod": (_binary_operate,),
- "truediv": (_binary_operate,),
- "floordiv": (_binary_operate,),
- "custom_op": (_custom_op_operate,),
- "json_path_getitem_op": (_binary_operate,),
- "json_getitem_op": (_binary_operate,),
- "concat_op": (_binary_operate,),
- "any_op": (_scalar, CollectionAggregate._create_any),
- "all_op": (_scalar, CollectionAggregate._create_all),
- "lt": (_boolean_compare, operators.ge),
- "le": (_boolean_compare, operators.gt),
- "ne": (_boolean_compare, operators.eq),
- "gt": (_boolean_compare, operators.le),
- "ge": (_boolean_compare, operators.lt),
- "eq": (_boolean_compare, operators.ne),
- "is_distinct_from": (_boolean_compare, operators.is_not_distinct_from),
- "is_not_distinct_from": (_boolean_compare, operators.is_distinct_from),
- "like_op": (_boolean_compare, operators.not_like_op),
- "ilike_op": (_boolean_compare, operators.not_ilike_op),
- "not_like_op": (_boolean_compare, operators.like_op),
- "not_ilike_op": (_boolean_compare, operators.ilike_op),
- "contains_op": (_boolean_compare, operators.not_contains_op),
- "startswith_op": (_boolean_compare, operators.not_startswith_op),
- "endswith_op": (_boolean_compare, operators.not_endswith_op),
- "desc_op": (_scalar, UnaryExpression._create_desc),
- "asc_op": (_scalar, UnaryExpression._create_asc),
- "nulls_first_op": (_scalar, UnaryExpression._create_nulls_first),
- "nulls_last_op": (_scalar, UnaryExpression._create_nulls_last),
- "in_op": (_in_impl, operators.not_in_op),
- "not_in_op": (_in_impl, operators.in_op),
- "is_": (_boolean_compare, operators.is_),
- "is_not": (_boolean_compare, operators.is_not),
- "collate": (_collate_impl,),
- "match_op": (_match_impl,),
- "not_match_op": (_match_impl,),
- "distinct_op": (_distinct_impl,),
- "between_op": (_between_impl,),
- "not_between_op": (_between_impl,),
- "neg": (_neg_impl,),
- "getitem": (_getitem_impl,),
- "lshift": (_unsupported_impl,),
- "rshift": (_unsupported_impl,),
- "contains": (_unsupported_impl,),
- "regexp_match_op": (_regexp_match_impl,),
- "not_regexp_match_op": (_regexp_match_impl,),
- "regexp_replace_op": (_regexp_replace_impl,),
+# additional keyword arguments to be passed
+operator_lookup: Dict[
+ str, Tuple[Callable[..., "ColumnElement"], util.immutabledict]
+] = {
+ "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),
+ "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}),
+ ),
+ "startswith_op": (
+ _boolean_compare,
+ util.immutabledict({"negate_op": operators.not_startswith_op}),
+ ),
+ "endswith_op": (
+ _boolean_compare,
+ util.immutabledict({"negate_op": operators.not_endswith_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),
}
+ HasCTE._has_ctes_traverse_internals
)
- def __init__(
- self,
- table,
- ):
- """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:`coretutorial_insert_expressions` - in the
- :ref:`1.x tutorial <sqlexpression_toplevel>`
-
- :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:`coretutorial_insert_expressions` - SQL Expression Tutorial
-
- :ref:`inserts_and_updates` - SQL Expression Tutorial
-
- """
+ def __init__(self, table):
super(Insert, self).__init__(table)
@_generative
+ HasCTE._has_ctes_traverse_internals
)
- def __init__(
- self,
- table,
- ):
- 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`.
-
- .. seealso::
-
- :ref:`inserts_and_updates` - in the
- :ref:`1.x tutorial <sqlexpression_toplevel>`
-
- :ref:`tutorial_core_update_delete` - in the :ref:`unified_tutorial`
-
-
-
- :param table: A :class:`_schema.Table`
- object representing the database
- table to be updated.
-
- :param whereclause: Optional SQL expression describing the ``WHERE``
- condition of the ``UPDATE`` statement; is equivalent to using the
- more modern :meth:`~Update.where()` method to specify the ``WHERE``
- clause.
-
- :param values:
- Optional dictionary which specifies the ``SET`` conditions of the
- ``UPDATE``. If left as ``None``, the ``SET``
- conditions are determined from those parameters passed to the
- statement during the execution and/or compilation of the
- statement. When compiled standalone without any parameters,
- the ``SET`` clause generates for all columns.
-
- Modern applications may prefer to use the generative
- :meth:`_expression.Update.values` method to set the values of the
- UPDATE statement.
-
- :param inline:
- if True, SQL defaults present on :class:`_schema.Column` objects via
- the ``default`` keyword will be compiled 'inline' into the statement
- and not pre-executed. This means that their values will not
- be available in the dictionary returned from
- :meth:`_engine.CursorResult.last_updated_params`.
-
- :param preserve_parameter_order: if True, the update statement is
- expected to receive parameters **only** via the
- :meth:`_expression.Update.values` method,
- and they must be passed as a Python
- ``list`` of 2-tuples. The rendered UPDATE statement will emit the SET
- clause for each referenced column maintaining this order.
-
- .. versionadded:: 1.0.10
-
- .. seealso::
-
- :ref:`updates_order_parameters` - illustrates the
- :meth:`_expression.Update.ordered_values` method.
-
- If both ``values`` and compile-time bind parameters are present, the
- compile-time bind parameters override the information specified
- within ``values`` on a per-key basis.
-
- The keys within ``values`` can be either :class:`_schema.Column`
- objects or their string identifiers (specifically the "key" of the
- :class:`_schema.Column`, normally but not necessarily equivalent to
- its "name"). Normally, the
- :class:`_schema.Column` objects used here are expected to be
- part of the target :class:`_schema.Table` that is the table
- to be updated. However when using MySQL, a multiple-table
- UPDATE statement can refer to columns from any of
- the tables referred to in the WHERE clause.
-
- The values referred to in ``values`` are typically:
-
- * a literal data value (i.e. string, number, etc.)
- * a SQL expression, such as a related :class:`_schema.Column`,
- a scalar-returning :func:`_expression.select` construct,
- etc.
-
- When combining :func:`_expression.select` constructs within the
- values clause of an :func:`_expression.update`
- construct, the subquery represented
- by the :func:`_expression.select` should be *correlated* to the
- parent table, that is, providing criterion which links the table inside
- the subquery to the outer table being updated::
-
- users.update().values(
- name=select(addresses.c.email_address).\
- where(addresses.c.user_id==users.c.id).\
- scalar_subquery()
- )
-
- .. seealso::
-
- :ref:`inserts_and_updates` - SQL Expression
- Language Tutorial
-
-
- """
+ def __init__(self, table):
super(Update, self).__init__(table)
@_generative
+ HasCTE._has_ctes_traverse_internals
)
- def __init__(
- self,
- table,
- ):
- 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`.
-
- .. seealso::
-
- :ref:`inserts_and_updates` - in the
- :ref:`1.x tutorial <sqlexpression_toplevel>`
-
- :ref:`tutorial_core_update_delete` - in the :ref:`unified_tutorial`
-
-
- :param table: The table to delete rows from.
-
- :param whereclause: Optional SQL expression describing the ``WHERE``
- condition of the ``DELETE`` statement; is equivalent to using the
- more modern :meth:`~Delete.where()` method to specify the ``WHERE``
- clause.
-
- .. seealso::
-
- :ref:`deletes` - SQL Expression Tutorial
-
- """
+ def __init__(self, table):
self.table = coercions.expect(
roles.DMLTableRole, table, apply_propagate_attrs=self
)
import operator
import re
import typing
+from typing import Any
+from typing import Callable
+from typing import Generic
+from typing import Optional
+from typing import overload
+from typing import Sequence
+from typing import Text as typing_Text
+from typing import Type
+from typing import TypeVar
+from typing import Union
from . import coercions
from . import operators
from .base import SingletonConstant
from .cache_key import MemoizedHasCacheKey
from .cache_key import NO_CACHE
-from .coercions import _document_text_coercion
+from .coercions import _document_text_coercion # noqa
from .traversals import HasCopyInternals
from .visitors import cloned_traverse
from .visitors import InternalTraversal
from .. import inspection
from .. import util
+if typing.TYPE_CHECKING:
+ from decimal import Decimal
-def collate(expression, collation):
- """Return the clause ``expression COLLATE collation``.
+ from .selectable import FromClause
+ from .selectable import Select
+ from .sqltypes import Boolean # noqa
+ from .type_api import TypeEngine
- e.g.::
+_NUMERIC = Union[complex, "Decimal"]
- collate(mycolumn, 'utf8_bin')
-
- produces::
-
- mycolumn COLLATE utf8_bin
-
- The collation expression is also quoted if it is a case sensitive
- identifier, e.g. contains uppercase characters.
-
- .. versionchanged:: 1.2 quoting is automatically applied to COLLATE
- expressions if they are case sensitive.
-
- """
-
- expr = coercions.expect(roles.ExpressionElementRole, expression)
- return BinaryExpression(
- expr, CollationClause(collation), operators.collate, type_=expr.type
- )
-
-
-def between(expr, lower_bound, upper_bound, symmetric=False):
- """Produce a ``BETWEEN`` predicate clause.
-
- E.g.::
-
- from sqlalchemy import between
- stmt = select(users_table).where(between(users_table.c.id, 5, 7))
-
- Would produce SQL resembling::
-
- SELECT id, name FROM user WHERE id BETWEEN :id_1 AND :id_2
-
- The :func:`.between` function is a standalone version of the
- :meth:`_expression.ColumnElement.between` method available on all
- SQL expressions, as in::
-
- stmt = select(users_table).where(users_table.c.id.between(5, 7))
-
- All arguments passed to :func:`.between`, including the left side
- column expression, are coerced from Python scalar values if a
- the value is not a :class:`_expression.ColumnElement` subclass.
- For example,
- three fixed values can be compared as in::
-
- print(between(5, 3, 7))
-
- Which would produce::
-
- :param_1 BETWEEN :param_2 AND :param_3
-
- :param expr: a column expression, typically a
- :class:`_expression.ColumnElement`
- instance or alternatively a Python scalar expression to be coerced
- into a column expression, serving as the left side of the ``BETWEEN``
- expression.
-
- :param lower_bound: a column or Python scalar expression serving as the
- lower bound of the right side of the ``BETWEEN`` expression.
-
- :param upper_bound: a column or Python scalar expression serving as the
- upper bound of the right side of the ``BETWEEN`` expression.
-
- :param symmetric: if True, will render " BETWEEN SYMMETRIC ". Note
- that not all databases support this syntax.
-
- .. versionadded:: 0.9.5
-
- .. seealso::
-
- :meth:`_expression.ColumnElement.between`
-
- """
- expr = coercions.expect(roles.ExpressionElementRole, expr)
- return expr.between(lower_bound, upper_bound, symmetric=symmetric)
+_T = TypeVar("_T", bound="Any")
+_OPT = TypeVar("_OPT", bound="Any")
+_NT = TypeVar("_NT", bound="_NUMERIC")
+_ST = TypeVar("_ST", bound="typing_Text")
def literal(value, type_=None):
return coercions.expect(roles.LiteralValueRole, value, type_=type_)
-def outparam(key, type_=None):
- """Create an 'OUT' parameter for usage in functions (stored procedures),
- for databases which support them.
+def literal_column(text, type_=None):
+ r"""Produce a :class:`.ColumnClause` object that has the
+ :paramref:`_expression.column.is_literal` flag set to True.
+
+ :func:`_expression.literal_column` is similar to
+ :func:`_expression.column`, except that
+ it is more often used as a "standalone" column expression that renders
+ exactly as stated; while :func:`_expression.column`
+ stores a string name that
+ will be assumed to be part of a table and may be quoted as such,
+ :func:`_expression.literal_column` can be that,
+ or any other arbitrary column-oriented
+ expression.
+
+ :param text: the text of the expression; can be any SQL expression.
+ Quoting rules will not be applied. To specify a column-name expression
+ which should be subject to quoting rules, use the :func:`column`
+ function.
- The ``outparam`` can be used like a regular function parameter.
- The "output" value will be available from the
- :class:`~sqlalchemy.engine.CursorResult` object via its ``out_parameters``
- attribute, which returns a dictionary containing the values.
+ :param type\_: an optional :class:`~sqlalchemy.types.TypeEngine`
+ object which will
+ provide result-set translation and additional expression semantics for
+ this column. If left as ``None`` the type will be :class:`.NullType`.
- """
- return BindParameter(key, None, type_=type_, unique=False, isoutparam=True)
+ .. seealso::
+ :func:`_expression.column`
-def not_(clause):
- """Return a negation of the given clause, i.e. ``NOT(clause)``.
+ :func:`_expression.text`
- The ``~`` operator is also overloaded on all
- :class:`_expression.ColumnElement` subclasses to produce the
- same result.
+ :ref:`sqlexpression_literal_column`
"""
- return operators.inv(coercions.expect(roles.ExpressionElementRole, clause))
+ return ColumnClause(text, type_=type_, is_literal=True)
class CompilerElement(Traversible):
return str(self.compile())
+SelfClauseElement = TypeVar("SelfClauseElement", bound="ClauseElement")
+
+
@inspection._self_inspects
class ClauseElement(
SupportsWrappingAnnotations,
self._propagate_attrs = util.immutabledict(values)
return self
- def _clone(self, **kw):
+ def _clone(self: SelfClauseElement, **kw) -> SelfClauseElement:
"""Create a shallow copy of this ClauseElement.
This method may be used by a generative API. Its also used as
roles.DMLColumnRole,
roles.DDLConstraintColumnRole,
roles.DDLExpressionRole,
- operators.ColumnOperators,
+ operators.ColumnOperators["ColumnElement"],
ClauseElement,
+ Generic[_T],
):
"""Represent a column-oriented SQL expression suitable for usage in the
"columns" clause, WHERE clause etc. of a statement.
return super(ColumnElement, self)._negate()
@util.memoized_property
- def type(self):
+ def type(self) -> "TypeEngine[_T]":
return type_api.NULLTYPE
@HasMemoized.memoized_attribute
- def comparator(self):
+ def comparator(self) -> "TypeEngine.Comparator[_T]":
try:
comparator_factory = self.type.comparator_factory
except AttributeError as err:
)
) from err
- def operate(self, op, *other, **kwargs):
+ # annotations for comparison methods
+ # these are from operators->Operators / ColumnOperators,
+ # redefined with the specific types returned by ColumnElement hierarchies
+ if typing.TYPE_CHECKING:
+
+ def op(
+ self,
+ opstring: Any,
+ precedence: int = 0,
+ is_comparison: bool = False,
+ return_type: Optional[
+ Union[Type["TypeEngine[_OPT]"], "TypeEngine[_OPT]"]
+ ] = None,
+ python_impl=None,
+ ) -> Callable[[Any], "BinaryExpression[_OPT]"]:
+ ...
+
+ def bool_op(
+ self, opstring: Any, precedence: int = 0, python_impl=None
+ ) -> Callable[[Any], "BinaryExpression[bool]"]:
+ ...
+
+ def __and__(self, other: Any) -> "BooleanClauseList":
+ ...
+
+ def __or__(self, other: Any) -> "BooleanClauseList":
+ ...
+
+ def __invert__(self) -> "UnaryExpression[_T]":
+ ...
+
+ def __lt__(self, other: Any) -> "BinaryExpression[bool]":
+ ...
+
+ def __le__(self, other: Any) -> "BinaryExpression[bool]":
+ ...
+
+ def __eq__(self, other: Any) -> "BinaryExpression[bool]":
+ ...
+
+ def __ne__(self, other: Any) -> "BinaryExpression[bool]":
+ ...
+
+ def is_distinct_from(self, other: Any) -> "BinaryExpression[bool]":
+ ...
+
+ def is_not_distinct_from(self, other: Any) -> "BinaryExpression[bool]":
+ ...
+
+ def __gt__(self, other: Any) -> "BinaryExpression[bool]":
+ ...
+
+ def __ge__(self, other: Any) -> "BinaryExpression[bool]":
+ ...
+
+ def __neg__(self) -> "UnaryExpression[_T]":
+ ...
+
+ def __contains__(self, other: Any) -> "BinaryExpression[bool]":
+ ...
+
+ def __getitem__(self, index: Any) -> "ColumnElement":
+ ...
+
+ @overload
+ def concat(self, other: Any) -> "BinaryExpression[_ST]":
+ ...
+
+ @overload
+ def concat(self, other: Any) -> "BinaryExpression":
+ ...
+
+ def concat(self, other: Any) -> "BinaryExpression":
+ ...
+
+ def like(self, other: Any, escape=None) -> "BinaryExpression[bool]":
+ ...
+
+ def ilike(self, other: Any, escape=None) -> "BinaryExpression[bool]":
+ ...
+
+ def in_(
+ self,
+ other: Union[Sequence[Any], "BindParameter", "Select"],
+ ) -> "BinaryExpression[bool]":
+ ...
+
+ def not_in(
+ self,
+ other: Union[Sequence[Any], "BindParameter", "Select"],
+ ) -> "BinaryExpression[bool]":
+ ...
+
+ def not_like(
+ self, other: Any, escape=None
+ ) -> "BinaryExpression[bool]":
+ ...
+
+ def not_ilike(
+ self, other: Any, escape=None
+ ) -> "BinaryExpression[bool]":
+ ...
+
+ def is_(self, other: Any) -> "BinaryExpression[bool]":
+ ...
+
+ def is_not(self, other: Any) -> "BinaryExpression[bool]":
+ ...
+
+ def startswith(
+ self, other: Any, escape=None, autoescape=False
+ ) -> "BinaryExpression[bool]":
+ ...
+
+ def endswith(
+ self, other: Any, escape=None, autoescape=False
+ ) -> "BinaryExpression[bool]":
+ ...
+
+ def contains(
+ self, other: Any, escape=None, autoescape=False
+ ) -> "BinaryExpression[bool]":
+ ...
+
+ def match(self, other: Any, **kwargs) -> "BinaryExpression[bool]":
+ ...
+
+ def regexp_match(
+ self, pattern, flags=None
+ ) -> "BinaryExpression[bool]":
+ ...
+
+ def regexp_replace(
+ self, pattern, replacement, flags=None
+ ) -> "BinaryExpression":
+ ...
+
+ def desc(self) -> "UnaryExpression[_T]":
+ ...
+
+ def asc(self) -> "UnaryExpression[_T]":
+ ...
+
+ def nulls_first(self) -> "UnaryExpression[_T]":
+ ...
+
+ def nulls_last(self) -> "UnaryExpression[_T]":
+ ...
+
+ def collate(self, collation) -> "CollationClause":
+ ...
+
+ def between(
+ self, cleft, cright, symmetric=False
+ ) -> "BinaryExpression[bool]":
+ ...
+
+ def distinct(self: "ColumnElement[_T]") -> "UnaryExpression[_T]":
+ ...
+
+ def any_(self) -> "CollectionAggregate":
+ ...
+
+ def all_(self) -> "CollectionAggregate":
+ ...
+
+ # numeric overloads. These need more tweaking
+
+ @overload
+ def __add__(
+ self: "ColumnElement[_NT]", other: "Union[ColumnElement[_NT], _NT]"
+ ) -> "BinaryExpression[_NT]":
+ ...
+
+ @overload
+ def __add__(
+ self: "ColumnElement[_NT]", other: Any
+ ) -> "BinaryExpression[_NUMERIC]":
+ ...
+
+ @overload
+ def __add__(
+ self: "ColumnElement[_ST]", other: Any
+ ) -> "BinaryExpression[_ST]":
+ ...
+
+ def __add__(self, other: Any) -> "BinaryExpression":
+ ...
+
+ @overload
+ def __radd__(self, other: Any) -> "BinaryExpression[_NUMERIC]":
+ ...
+
+ @overload
+ def __radd__(self, other: Any) -> "BinaryExpression":
+ ...
+
+ def __radd__(self, other: Any) -> "BinaryExpression":
+ ...
+
+ @overload
+ def __sub__(
+ self: "ColumnElement[_NT]", other: "Union[ColumnElement[_NT], _NT]"
+ ) -> "BinaryExpression[_NT]":
+ ...
+
+ @overload
+ def __sub__(self, other: Any) -> "BinaryExpression":
+ ...
+
+ def __sub__(self, other: Any) -> "BinaryExpression":
+ ...
+
+ @overload
+ def __rsub__(
+ self: "ColumnElement[_NT]", other: Any
+ ) -> "BinaryExpression[_NUMERIC]":
+ ...
+
+ @overload
+ def __rsub__(self, other: Any) -> "BinaryExpression":
+ ...
+
+ def __rsub__(self, other: Any) -> "BinaryExpression":
+ ...
+
+ @overload
+ def __mul__(
+ self: "ColumnElement[_NT]", other: Any
+ ) -> "BinaryExpression[_NUMERIC]":
+ ...
+
+ @overload
+ def __mul__(self, other: Any) -> "BinaryExpression":
+ ...
+
+ def __mul__(self, other: Any) -> "BinaryExpression":
+ ...
+
+ @overload
+ def __rmul__(
+ self: "ColumnElement[_NT]", other: Any
+ ) -> "BinaryExpression[_NUMERIC]":
+ ...
+
+ @overload
+ def __rmul__(self, other: Any) -> "BinaryExpression":
+ ...
+
+ def __rmul__(self, other: Any) -> "BinaryExpression":
+ ...
+
+ @overload
+ def __mod__(
+ self: "ColumnElement[_NT]", other: Any
+ ) -> "BinaryExpression[_NUMERIC]":
+ ...
+
+ @overload
+ def __mod__(self, other: Any) -> "BinaryExpression":
+ ...
+
+ def __mod__(self, other: Any) -> "BinaryExpression":
+ ...
+
+ @overload
+ def __rmod__(
+ self: "ColumnElement[_NT]", other: Any
+ ) -> "BinaryExpression[_NUMERIC]":
+ ...
+
+ @overload
+ def __rmod__(self, other: Any) -> "BinaryExpression":
+ ...
+
+ def __rmod__(self, other: Any) -> "BinaryExpression":
+ ...
+
+ @overload
+ def __truediv__(
+ self: "ColumnElement[_NT]", other: Any
+ ) -> "BinaryExpression[_NUMERIC]":
+ ...
+
+ @overload
+ def __truediv__(self, other: Any) -> "BinaryExpression":
+ ...
+
+ def __truediv__(self, other: Any) -> "BinaryExpression":
+ ...
+
+ @overload
+ def __rtruediv__(
+ self: "ColumnElement[_NT]", other: Any
+ ) -> "BinaryExpression[_NUMERIC]":
+ ...
+
+ @overload
+ def __rtruediv__(self, other: Any) -> "BinaryExpression":
+ ...
+
+ def __rtruediv__(self, other: Any) -> "BinaryExpression":
+ ...
+
+ @overload
+ def __floordiv__(
+ self: "ColumnElement[_NT]", other: Any
+ ) -> "BinaryExpression[_NUMERIC]":
+ ...
+
+ @overload
+ def __floordiv__(self, other: Any) -> "BinaryExpression":
+ ...
+
+ def __floordiv__(self, other: Any) -> "BinaryExpression":
+ ...
+
+ @overload
+ def __rfloordiv__(
+ self: "ColumnElement[_NT]", other: Any
+ ) -> "BinaryExpression[_NUMERIC]":
+ ...
+
+ @overload
+ def __rfloordiv__(self, other: Any) -> "BinaryExpression":
+ ...
+
+ def __rfloordiv__(self, other: Any) -> "BinaryExpression":
+ ...
+
+ def operate(
+ self,
+ op: operators.OperatorType,
+ *other: Any,
+ **kwargs,
+ ) -> "ColumnElement":
return op(self.comparator, *other, **kwargs)
- def reverse_operate(self, op, other, **kwargs):
+ def reverse_operate(
+ self, op: operators.OperatorType, other: Any, **kwargs
+ ) -> "ColumnElement":
return op(other, self.comparator, **kwargs)
def _bind_param(self, operator, obj, type_=None, expanding=False):
return None
def _make_proxy(
- self, selectable, name=None, key=None, name_is_truncatable=False, **kw
+ self,
+ selectable,
+ name: Optional[str] = None,
+ key=None,
+ name_is_truncatable=False,
+ **kw,
):
"""Create a new :class:`_expression.ColumnElement` representing this
:class:`_expression.ColumnElement` as it appears in the select list of
"""
return Label(name, self, self.type)
- def _anon_label(self, seed, add_hash=None):
+ def _anon_label(self, seed, add_hash=None) -> "_anonymous_label":
while self._is_clone_of is not None:
self = self._is_clone_of
return _anonymous_label.safe_construct(hash_value, seed or "anon")
@util.memoized_property
- def _anon_name_label(self):
+ def _anon_name_label(self) -> "_anonymous_label":
"""Provides a constant 'anonymous label' for this ColumnElement.
This is a label() expression which will be named at compile time.
return self._dedupe_anon_tq_label_idx(idx)
-class BindParameter(roles.InElementRole, ColumnElement):
+SelfBindParameter = TypeVar("SelfBindParameter", bound="BindParameter")
+
+
+class BindParameter(roles.InElementRole, ColumnElement[_T]):
r"""Represent a "bound expression".
:class:`.BindParameter` is invoked explicitly using the
_compared_to_type=None,
_is_crud=False,
):
- r"""Produce a "bound expression".
-
- The return value is an instance of :class:`.BindParameter`; this
- is a :class:`_expression.ColumnElement`
- subclass which represents a so-called
- "placeholder" value in a SQL expression, the value of which is
- supplied at the point at which the statement in executed against a
- database connection.
-
- In SQLAlchemy, the :func:`.bindparam` construct has
- the ability to carry along the actual value that will be ultimately
- used at expression time. In this way, it serves not just as
- a "placeholder" for eventual population, but also as a means of
- representing so-called "unsafe" values which should not be rendered
- directly in a SQL statement, but rather should be passed along
- to the :term:`DBAPI` as values which need to be correctly escaped
- and potentially handled for type-safety.
-
- When using :func:`.bindparam` explicitly, the use case is typically
- one of traditional deferment of parameters; the :func:`.bindparam`
- construct accepts a name which can then be referred to at execution
- time::
-
- from sqlalchemy import bindparam
-
- stmt = select(users_table).\
- where(users_table.c.name == bindparam('username'))
-
- The above statement, when rendered, will produce SQL similar to::
-
- SELECT id, name FROM user WHERE name = :username
-
- In order to populate the value of ``:username`` above, the value
- would typically be applied at execution time to a method
- like :meth:`_engine.Connection.execute`::
-
- result = connection.execute(stmt, username='wendy')
-
- Explicit use of :func:`.bindparam` is also common when producing
- UPDATE or DELETE statements that are to be invoked multiple times,
- where the WHERE criterion of the statement is to change on each
- invocation, such as::
-
- stmt = (users_table.update().
- where(user_table.c.name == bindparam('username')).
- values(fullname=bindparam('fullname'))
- )
-
- connection.execute(
- stmt, [{"username": "wendy", "fullname": "Wendy Smith"},
- {"username": "jack", "fullname": "Jack Jones"},
- ]
- )
-
- SQLAlchemy's Core expression system makes wide use of
- :func:`.bindparam` in an implicit sense. It is typical that Python
- literal values passed to virtually all SQL expression functions are
- coerced into fixed :func:`.bindparam` constructs. For example, given
- a comparison operation such as::
-
- expr = users_table.c.name == 'Wendy'
-
- The above expression will produce a :class:`.BinaryExpression`
- construct, where the left side is the :class:`_schema.Column` object
- representing the ``name`` column, and the right side is a
- :class:`.BindParameter` representing the literal value::
-
- print(repr(expr.right))
- BindParameter('%(4327771088 name)s', 'Wendy', type_=String())
-
- The expression above will render SQL such as::
-
- user.name = :name_1
-
- Where the ``:name_1`` parameter name is an anonymous name. The
- actual string ``Wendy`` is not in the rendered string, but is carried
- along where it is later used within statement execution. If we
- invoke a statement like the following::
-
- stmt = select(users_table).where(users_table.c.name == 'Wendy')
- result = connection.execute(stmt)
-
- We would see SQL logging output as::
-
- SELECT "user".id, "user".name
- FROM "user"
- WHERE "user".name = %(name_1)s
- {'name_1': 'Wendy'}
-
- Above, we see that ``Wendy`` is passed as a parameter to the database,
- while the placeholder ``:name_1`` is rendered in the appropriate form
- for the target database, in this case the PostgreSQL database.
-
- Similarly, :func:`.bindparam` is invoked automatically when working
- with :term:`CRUD` statements as far as the "VALUES" portion is
- concerned. The :func:`_expression.insert` construct produces an
- ``INSERT`` expression which will, at statement execution time, generate
- bound placeholders based on the arguments passed, as in::
-
- stmt = users_table.insert()
- result = connection.execute(stmt, name='Wendy')
-
- The above will produce SQL output as::
-
- INSERT INTO "user" (name) VALUES (%(name)s)
- {'name': 'Wendy'}
-
- The :class:`_expression.Insert` construct, at
- compilation/execution time, rendered a single :func:`.bindparam`
- mirroring the column name ``name`` as a result of the single ``name``
- parameter we passed to the :meth:`_engine.Connection.execute` method.
-
- :param key:
- the key (e.g. the name) for this bind param.
- Will be used in the generated
- SQL statement for dialects that use named parameters. This
- value may be modified when part of a compilation operation,
- if other :class:`BindParameter` objects exist with the same
- key, or if its length is too long and truncation is
- required.
-
- :param value:
- Initial value for this bind param. Will be used at statement
- execution time as the value for this parameter passed to the
- DBAPI, if no other value is indicated to the statement execution
- method for this particular parameter name. Defaults to ``None``.
-
- :param callable\_:
- A callable function that takes the place of "value". The function
- will be called at statement execution time to determine the
- ultimate value. Used for scenarios where the actual bind
- value cannot be determined at the point at which the clause
- construct is created, but embedded bind values are still desirable.
-
- :param type\_:
- A :class:`.TypeEngine` class or instance representing an optional
- datatype for this :func:`.bindparam`. If not passed, a type
- may be determined automatically for the bind, based on the given
- value; for example, trivial Python types such as ``str``,
- ``int``, ``bool``
- may result in the :class:`.String`, :class:`.Integer` or
- :class:`.Boolean` types being automatically selected.
-
- The type of a :func:`.bindparam` is significant especially in that
- the type will apply pre-processing to the value before it is
- passed to the database. For example, a :func:`.bindparam` which
- refers to a datetime value, and is specified as holding the
- :class:`.DateTime` type, may apply conversion needed to the
- value (such as stringification on SQLite) before passing the value
- to the database.
-
- :param unique:
- if True, the key name of this :class:`.BindParameter` will be
- modified if another :class:`.BindParameter` of the same name
- already has been located within the containing
- expression. This flag is used generally by the internals
- when producing so-called "anonymous" bound expressions, it
- isn't generally applicable to explicitly-named :func:`.bindparam`
- constructs.
-
- :param required:
- If ``True``, a value is required at execution time. If not passed,
- it defaults to ``True`` if neither :paramref:`.bindparam.value`
- or :paramref:`.bindparam.callable` were passed. If either of these
- parameters are present, then :paramref:`.bindparam.required`
- defaults to ``False``.
-
- :param quote:
- True if this parameter name requires quoting and is not
- currently known as a SQLAlchemy reserved word; this currently
- only applies to the Oracle backend, where bound names must
- sometimes be quoted.
-
- :param isoutparam:
- if True, the parameter should be treated like a stored procedure
- "OUT" parameter. This applies to backends such as Oracle which
- support OUT parameters.
-
- :param expanding:
- if True, this parameter will be treated as an "expanding" parameter
- at execution time; the parameter value is expected to be a sequence,
- rather than a scalar value, and the string SQL statement will
- be transformed on a per-execution basis to accommodate the sequence
- with a variable number of parameter slots passed to the DBAPI.
- This is to allow statement caching to be used in conjunction with
- an IN clause.
-
- .. seealso::
-
- :meth:`.ColumnOperators.in_`
-
- :ref:`baked_in` - with baked queries
-
- .. note:: The "expanding" feature does not support "executemany"-
- style parameter sets.
-
- .. versionadded:: 1.2
-
- .. versionchanged:: 1.3 the "expanding" bound parameter feature now
- supports empty lists.
-
-
- .. seealso::
-
- :ref:`coretutorial_bind_param`
-
- :ref:`coretutorial_insert_expressions`
-
- :func:`.outparam`
-
- :param literal_execute:
- if True, the bound parameter will be rendered in the compile phase
- with a special "POSTCOMPILE" token, and the SQLAlchemy compiler will
- render the final value of the parameter into the SQL statement at
- statement execution time, omitting the value from the parameter
- dictionary / list passed to DBAPI ``cursor.execute()``. This
- produces a similar effect as that of using the ``literal_binds``,
- compilation flag, however takes place as the statement is sent to
- the DBAPI ``cursor.execute()`` method, rather than when the statement
- is compiled. The primary use of this
- capability is for rendering LIMIT / OFFSET clauses for database
- drivers that can't accommodate for bound parameters in these
- contexts, while allowing SQL constructs to be cacheable at the
- compilation level.
-
- .. versionadded:: 1.4 Added "post compile" bound parameters
-
- .. seealso::
-
- :ref:`change_4808`.
-
- """
if required is NO_ARG:
required = value is NO_ARG and callable_ is None
if value is NO_ARG:
c.type = type_
return c
- def _clone(self, maintain_key=False, **kw):
+ def _clone(
+ self: SelfBindParameter, maintain_key=False, **kw
+ ) -> SelfBindParameter:
c = ClauseElement._clone(self, **kw)
if not maintain_key and self.unique:
c.key = _anonymous_label.safe_construct(
# to the list of bindparams
self.text = self._bind_params_regex.sub(repl, text)
- @classmethod
- @_document_text_coercion("text", ":func:`.text`", ":paramref:`.text.text`")
- def _create_text(cls, text):
- r"""Construct a new :class:`_expression.TextClause` clause,
- representing
- a textual SQL string directly.
-
- E.g.::
-
- from sqlalchemy import text
-
- t = text("SELECT * FROM users")
- result = connection.execute(t)
-
- The advantages :func:`_expression.text`
- provides over a plain string are
- backend-neutral support for bind parameters, per-statement
- execution options, as well as
- bind parameter and result-column typing behavior, allowing
- SQLAlchemy type constructs to play a role when executing
- a statement that is specified literally. The construct can also
- be provided with a ``.c`` collection of column elements, allowing
- it to be embedded in other SQL expression constructs as a subquery.
-
- Bind parameters are specified by name, using the format ``:name``.
- E.g.::
-
- t = text("SELECT * FROM users WHERE id=:user_id")
- result = connection.execute(t, user_id=12)
-
- For SQL statements where a colon is required verbatim, as within
- an inline string, use a backslash to escape::
-
- t = text("SELECT * FROM users WHERE name='\:username'")
-
- The :class:`_expression.TextClause`
- construct includes methods which can
- provide information about the bound parameters as well as the column
- values which would be returned from the textual statement, assuming
- it's an executable SELECT type of statement. The
- :meth:`_expression.TextClause.bindparams`
- method is used to provide bound
- parameter detail, and :meth:`_expression.TextClause.columns`
- method allows
- specification of return columns including names and types::
-
- t = text("SELECT * FROM users WHERE id=:user_id").\
- bindparams(user_id=7).\
- columns(id=Integer, name=String)
-
- for id, name in connection.execute(t):
- print(id, name)
-
- The :func:`_expression.text` construct is used in cases when
- a literal string SQL fragment is specified as part of a larger query,
- such as for the WHERE clause of a SELECT statement::
-
- s = select(users.c.id, users.c.name).where(text("id=:user_id"))
- result = connection.execute(s, user_id=12)
-
- :func:`_expression.text` is also used for the construction
- of a full, standalone statement using plain text.
- As such, SQLAlchemy refers
- to it as an :class:`.Executable` object and may be used
- like any other statement passed to an ``.execute()`` method.
-
- :param text:
- the text of the SQL statement to be created. Use ``:<param>``
- to specify bind parameters; they will be compiled to their
- engine-specific format.
-
- .. seealso::
-
- :ref:`sqlexpression_text` - in the Core tutorial
-
-
- """
- return TextClause(text)
-
@_generative
def bindparams(
self: SelfTextClause, *binds, **names_to_values
@classmethod
def _instance(cls):
- """Return a :class:`.False_` construct.
-
- E.g.::
-
- >>> from sqlalchemy import false
- >>> print(select(t.c.x).where(false()))
- SELECT x FROM t WHERE false
-
- A backend which does not support true/false constants will render as
- an expression against 1 or 0::
-
- >>> print(select(t.c.x).where(false()))
- SELECT x FROM t WHERE 0 = 1
-
- The :func:`.true` and :func:`.false` constants also feature
- "short circuit" operation within an :func:`.and_` or :func:`.or_`
- conjunction::
-
- >>> print(select(t.c.x).where(or_(t.c.x > 5, true())))
- SELECT x FROM t WHERE true
-
- >>> print(select(t.c.x).where(and_(t.c.x > 5, false())))
- SELECT x FROM t WHERE false
-
- .. versionchanged:: 0.9 :func:`.true` and :func:`.false` feature
- better integrated behavior within conjunctions and on dialects
- that don't support true/false constants.
-
- .. seealso::
-
- :func:`.true`
-
- """
-
return False_()
@classmethod
def _instance(cls):
- """Return a constant :class:`.True_` construct.
-
- E.g.::
-
- >>> from sqlalchemy import true
- >>> print(select(t.c.x).where(true()))
- SELECT x FROM t WHERE true
-
- A backend which does not support true/false constants will render as
- an expression against 1 or 0::
-
- >>> print(select(t.c.x).where(true()))
- SELECT x FROM t WHERE 1 = 1
-
- The :func:`.true` and :func:`.false` constants also feature
- "short circuit" operation within an :func:`.and_` or :func:`.or_`
- conjunction::
-
- >>> print(select(t.c.x).where(or_(t.c.x > 5, true())))
- SELECT x FROM t WHERE true
-
- >>> print(select(t.c.x).where(and_(t.c.x > 5, false())))
- SELECT x FROM t WHERE false
-
- .. versionchanged:: 0.9 :func:`.true` and :func:`.false` feature
- better integrated behavior within conjunctions and on dialects
- that don't support true/false constants.
-
- .. seealso::
-
- :func:`.false`
-
- """
-
return True_()
("operator", InternalTraversal.dp_operator),
]
- def __init__(self, *clauses, **kwargs):
- self.operator = kwargs.pop("operator", operators.comma_op)
- self.group = kwargs.pop("group", True)
- self.group_contents = kwargs.pop("group_contents", True)
- if kwargs.pop("_flatten_sub_clauses", False):
+ def __init__(
+ self,
+ *clauses,
+ operator=operators.comma_op,
+ group=True,
+ group_contents=True,
+ _flatten_sub_clauses=False,
+ _literal_as_text_role: Type[roles.SQLRole] = roles.WhereHavingRole,
+ ):
+ self.operator = operator
+ self.group = group
+ self.group_contents = group_contents
+ if _flatten_sub_clauses:
clauses = util.flatten_iterator(clauses)
- self._text_converter_role = text_converter_role = kwargs.pop(
- "_literal_as_text_role", roles.WhereHavingRole
- )
+ self._text_converter_role: Type[roles.SQLRole] = _literal_as_text_role
+ text_converter_role: Type[roles.SQLRole] = _literal_as_text_role
+
if self.group_contents:
self.clauses = [
coercions.expect(
return self
-class BooleanClauseList(ClauseList, ColumnElement):
+class BooleanClauseList(ClauseList, ColumnElement[bool]):
__visit_name__ = "clauselist"
inherit_cache = True
def and_(cls, *clauses):
r"""Produce a conjunction of expressions joined by ``AND``.
- E.g.::
-
- from sqlalchemy import and_
-
- stmt = select(users_table).where(
- and_(
- users_table.c.name == 'wendy',
- users_table.c.enrolled == True
- )
- )
-
- The :func:`.and_` conjunction is also available using the
- Python ``&`` operator (though note that compound expressions
- need to be parenthesized in order to function with Python
- operator precedence behavior)::
-
- stmt = select(users_table).where(
- (users_table.c.name == 'wendy') &
- (users_table.c.enrolled == True)
- )
-
- The :func:`.and_` operation is also implicit in some cases;
- the :meth:`_expression.Select.where`
- method for example can be invoked multiple
- times against a statement, which will have the effect of each
- clause being combined using :func:`.and_`::
-
- stmt = select(users_table).\
- where(users_table.c.name == 'wendy').\
- where(users_table.c.enrolled == True)
-
- The :func:`.and_` construct must be given at least one positional
- argument in order to be valid; a :func:`.and_` construct with no
- arguments is ambiguous. To produce an "empty" or dynamically
- generated :func:`.and_` expression, from a given list of expressions,
- a "default" element of ``True`` should be specified::
-
- criteria = and_(True, *expressions)
-
- The above expression will compile to SQL as the expression ``true``
- or ``1 = 1``, depending on backend, if no other expressions are
- present. If expressions are present, then the ``True`` value is
- ignored as it does not affect the outcome of an AND expression that
- has other elements.
-
- .. deprecated:: 1.4 The :func:`.and_` element now requires that at
- least one argument is passed; creating the :func:`.and_` construct
- with no arguments is deprecated, and will emit a deprecation warning
- while continuing to produce a blank SQL string.
-
- .. seealso::
-
- :func:`.or_`
-
+ See :func:`_sql.and_` for full documentation.
"""
return cls._construct(
operators.and_, True_._singleton, False_._singleton, *clauses
def or_(cls, *clauses):
"""Produce a conjunction of expressions joined by ``OR``.
- E.g.::
-
- from sqlalchemy import or_
-
- stmt = select(users_table).where(
- or_(
- users_table.c.name == 'wendy',
- users_table.c.name == 'jack'
- )
- )
-
- The :func:`.or_` conjunction is also available using the
- Python ``|`` operator (though note that compound expressions
- need to be parenthesized in order to function with Python
- operator precedence behavior)::
-
- stmt = select(users_table).where(
- (users_table.c.name == 'wendy') |
- (users_table.c.name == 'jack')
- )
-
- The :func:`.or_` construct must be given at least one positional
- argument in order to be valid; a :func:`.or_` construct with no
- arguments is ambiguous. To produce an "empty" or dynamically
- generated :func:`.or_` expression, from a given list of expressions,
- a "default" element of ``False`` should be specified::
-
- or_criteria = or_(False, *expressions)
-
- The above expression will compile to SQL as the expression ``false``
- or ``0 = 1``, depending on backend, if no other expressions are
- present. If expressions are present, then the ``False`` value is
- ignored as it does not affect the outcome of an OR expression which
- has other elements.
-
- .. deprecated:: 1.4 The :func:`.or_` element now requires that at
- least one argument is passed; creating the :func:`.or_` construct
- with no arguments is deprecated, and will emit a deprecation warning
- while continuing to produce a blank SQL string.
-
- .. seealso::
-
- :func:`.and_`
-
+ See :func:`_sql.or_` for full documentation.
"""
return cls._construct(
operators.or_, False_._singleton, True_._singleton, *clauses
_traverse_internals = ClauseList._traverse_internals + []
@util.preload_module("sqlalchemy.sql.sqltypes")
- def __init__(self, *clauses, **kw):
- """Return a :class:`.Tuple`.
-
- Main usage is to produce a composite IN construct using
- :meth:`.ColumnOperators.in_` ::
-
- from sqlalchemy import tuple_
-
- tuple_(table.c.col1, table.c.col2).in_(
- [(1, 2), (5, 12), (10, 19)]
- )
-
- .. versionchanged:: 1.3.6 Added support for SQLite IN tuples.
-
- .. warning::
-
- The composite IN construct is not supported by all backends, and is
- currently known to work on PostgreSQL, MySQL, and SQLite.
- Unsupported backends will raise a subclass of
- :class:`~sqlalchemy.exc.DBAPIError` when such an expression is
- invoked.
-
- """
+ def __init__(self, *clauses, types=None):
sqltypes = util.preloaded.sql_sqltypes
- types = kw.pop("types", None)
if types is None:
clauses = [
coercions.expect(roles.ExpressionElementRole, c)
]
self.type = sqltypes.TupleType(*[arg.type for arg in clauses])
- super(Tuple, self).__init__(*clauses, **kw)
+ super(Tuple, self).__init__(*clauses)
@property
def _select_iterable(self):
return self
-class Case(ColumnElement):
+class Case(ColumnElement[_T]):
"""Represent a ``CASE`` expression.
:class:`.Case` is produced using the :func:`.case` factory function,
("else_", InternalTraversal.dp_clauseelement),
]
+ # for case(), the type is derived from the whens. so for the moment
+ # users would have to cast() the case to get a specific type
+
def __init__(self, *whens, value=None, else_=None):
- r"""Produce a ``CASE`` expression.
- The ``CASE`` construct in SQL is a conditional object that
- acts somewhat analogously to an "if/then" construct in other
- languages. It returns an instance of :class:`.Case`.
+ whens = coercions._expression_collection_was_a_list(
+ "whens", "case", whens
+ )
+ try:
+ whens = util.dictlike_iteritems(whens)
+ except TypeError:
+ pass
- :func:`.case` in its usual form is passed a series of "when"
- constructs, that is, a list of conditions and results as tuples::
+ whenlist = [
+ (
+ coercions.expect(
+ roles.ExpressionElementRole,
+ c,
+ apply_propagate_attrs=self,
+ ).self_group(),
+ coercions.expect(roles.ExpressionElementRole, r),
+ )
+ for (c, r) in whens
+ ]
- from sqlalchemy import case
-
- stmt = select(users_table).\
- where(
- case(
- (users_table.c.name == 'wendy', 'W'),
- (users_table.c.name == 'jack', 'J'),
- else_='E'
- )
- )
-
- The above statement will produce SQL resembling::
-
- SELECT id, name FROM user
- WHERE CASE
- WHEN (name = :name_1) THEN :param_1
- WHEN (name = :name_2) THEN :param_2
- ELSE :param_3
- END
-
- When simple equality expressions of several values against a single
- parent column are needed, :func:`.case` also has a "shorthand" format
- used via the
- :paramref:`.case.value` parameter, which is passed a column
- expression to be compared. In this form, the :paramref:`.case.whens`
- parameter is passed as a dictionary containing expressions to be
- compared against keyed to result expressions. The statement below is
- equivalent to the preceding statement::
-
- stmt = select(users_table).\
- where(
- case(
- {"wendy": "W", "jack": "J"},
- value=users_table.c.name,
- else_='E'
- )
- )
-
- The values which are accepted as result values in
- :paramref:`.case.whens` as well as with :paramref:`.case.else_` are
- coerced from Python literals into :func:`.bindparam` constructs.
- SQL expressions, e.g. :class:`_expression.ColumnElement` constructs,
- are accepted
- as well. To coerce a literal string expression into a constant
- expression rendered inline, use the :func:`_expression.literal_column`
- construct,
- as in::
-
- from sqlalchemy import case, literal_column
-
- case(
- (
- orderline.c.qty > 100,
- literal_column("'greaterthan100'")
- ),
- (
- orderline.c.qty > 10,
- literal_column("'greaterthan10'")
- ),
- else_=literal_column("'lessthan10'")
- )
-
- The above will render the given constants without using bound
- parameters for the result values (but still for the comparison
- values), as in::
-
- CASE
- WHEN (orderline.qty > :qty_1) THEN 'greaterthan100'
- WHEN (orderline.qty > :qty_2) THEN 'greaterthan10'
- ELSE 'lessthan10'
- END
-
- :param \*whens: The criteria to be compared against,
- :paramref:`.case.whens` accepts two different forms, based on
- whether or not :paramref:`.case.value` is used.
-
- .. versionchanged:: 1.4 the :func:`_sql.case`
- function now accepts the series of WHEN conditions positionally
-
- In the first form, it accepts a list of 2-tuples; each 2-tuple
- consists of ``(<sql expression>, <value>)``, where the SQL
- expression is a boolean expression and "value" is a resulting value,
- e.g.::
-
- case(
- (users_table.c.name == 'wendy', 'W'),
- (users_table.c.name == 'jack', 'J')
- )
-
- In the second form, it accepts a Python dictionary of comparison
- values mapped to a resulting value; this form requires
- :paramref:`.case.value` to be present, and values will be compared
- using the ``==`` operator, e.g.::
-
- case(
- {"wendy": "W", "jack": "J"},
- value=users_table.c.name
- )
-
- :param value: An optional SQL expression which will be used as a
- fixed "comparison point" for candidate values within a dictionary
- passed to :paramref:`.case.whens`.
-
- :param else\_: An optional SQL expression which will be the evaluated
- result of the ``CASE`` construct if all expressions within
- :paramref:`.case.whens` evaluate to false. When omitted, most
- databases will produce a result of NULL if none of the "when"
- expressions evaluate to true.
-
-
- """
-
- whens = coercions._expression_collection_was_a_list(
- "whens", "case", whens
- )
- try:
- whens = util.dictlike_iteritems(whens)
- except TypeError:
- pass
-
- whenlist = [
- (
- coercions.expect(
- roles.ExpressionElementRole,
- c,
- apply_propagate_attrs=self,
- ).self_group(),
- coercions.expect(roles.ExpressionElementRole, r),
- )
- for (c, r) in whens
- ]
-
- if whenlist:
- type_ = list(whenlist[-1])[-1].type
- else:
- type_ = None
+ if whenlist:
+ type_ = list(whenlist[-1])[-1].type
+ else:
+ type_ = None
if value is None:
self.value = None
)
-def literal_column(text, type_=None):
- r"""Produce a :class:`.ColumnClause` object that has the
- :paramref:`_expression.column.is_literal` flag set to True.
-
- :func:`_expression.literal_column` is similar to
- :func:`_expression.column`, except that
- it is more often used as a "standalone" column expression that renders
- exactly as stated; while :func:`_expression.column`
- stores a string name that
- will be assumed to be part of a table and may be quoted as such,
- :func:`_expression.literal_column` can be that,
- or any other arbitrary column-oriented
- expression.
-
- :param text: the text of the expression; can be any SQL expression.
- Quoting rules will not be applied. To specify a column-name expression
- which should be subject to quoting rules, use the :func:`column`
- function.
-
- :param type\_: an optional :class:`~sqlalchemy.types.TypeEngine`
- object which will
- provide result-set translation and additional expression semantics for
- this column. If left as ``None`` the type will be :class:`.NullType`.
-
- .. seealso::
-
- :func:`_expression.column`
-
- :func:`_expression.text`
-
- :ref:`sqlexpression_literal_column`
-
- """
- return ColumnClause(text, type_=type_, is_literal=True)
-
-
-class Cast(WrapsColumnExpression, ColumnElement):
+class Cast(WrapsColumnExpression, ColumnElement[_T]):
"""Represent a ``CAST`` expression.
:class:`.Cast` is produced using the :func:`.cast` factory function,
]
def __init__(self, expression, type_):
- r"""Produce a ``CAST`` expression.
-
- :func:`.cast` returns an instance of :class:`.Cast`.
-
- E.g.::
-
- from sqlalchemy import cast, Numeric
-
- stmt = select(cast(product_table.c.unit_price, Numeric(10, 4)))
-
- The above statement will produce SQL resembling::
-
- SELECT CAST(unit_price AS NUMERIC(10, 4)) FROM product
-
- The :func:`.cast` function performs two distinct functions when
- used. The first is that it renders the ``CAST`` expression within
- the resulting SQL string. The second is that it associates the given
- type (e.g. :class:`.TypeEngine` class or instance) with the column
- expression on the Python side, which means the expression will take
- on the expression operator behavior associated with that type,
- as well as the bound-value handling and result-row-handling behavior
- of the type.
-
- .. versionchanged:: 0.9.0 :func:`.cast` now applies the given type
- to the expression such that it takes effect on the bound-value,
- e.g. the Python-to-database direction, in addition to the
- result handling, e.g. database-to-Python, direction.
-
- An alternative to :func:`.cast` is the :func:`.type_coerce` function.
- This function performs the second task of associating an expression
- with a specific type, but does not render the ``CAST`` expression
- in SQL.
-
- :param expression: A SQL expression, such as a
- :class:`_expression.ColumnElement`
- expression or a Python string which will be coerced into a bound
- literal value.
-
- :param type\_: A :class:`.TypeEngine` class or instance indicating
- the type to which the ``CAST`` should apply.
-
- .. seealso::
-
- :ref:`coretutorial_casts`
-
- :func:`.type_coerce` - an alternative to CAST that coerces the type
- on the Python side only, which is often sufficient to generate the
- correct SQL and data coercion.
-
-
- """
self.type = type_api.to_instance(type_)
self.clause = coercions.expect(
roles.ExpressionElementRole,
return self.clause
-class TypeCoerce(WrapsColumnExpression, ColumnElement):
+class TypeCoerce(WrapsColumnExpression, ColumnElement[_T]):
"""Represent a Python-side type-coercion wrapper.
:class:`.TypeCoerce` supplies the :func:`_expression.type_coerce`
]
def __init__(self, expression, type_):
- r"""Associate a SQL expression with a particular type, without rendering
- ``CAST``.
-
- E.g.::
-
- from sqlalchemy import type_coerce
-
- stmt = select(type_coerce(log_table.date_string, StringDateTime()))
-
- The above construct will produce a :class:`.TypeCoerce` object, which
- does not modify the rendering in any way on the SQL side, with the
- possible exception of a generated label if used in a columns clause
- context::
-
- SELECT date_string AS date_string FROM log
-
- When result rows are fetched, the ``StringDateTime`` type processor
- will be applied to result rows on behalf of the ``date_string`` column.
-
- .. note:: the :func:`.type_coerce` construct does not render any
- SQL syntax of its own, including that it does not imply
- parenthesization. Please use :meth:`.TypeCoerce.self_group`
- if explicit parenthesization is required.
-
- In order to provide a named label for the expression, use
- :meth:`_expression.ColumnElement.label`::
-
- stmt = select(
- type_coerce(log_table.date_string, StringDateTime()).label('date')
- )
-
-
- A type that features bound-value handling will also have that behavior
- take effect when literal values or :func:`.bindparam` constructs are
- passed to :func:`.type_coerce` as targets.
- For example, if a type implements the
- :meth:`.TypeEngine.bind_expression`
- method or :meth:`.TypeEngine.bind_processor` method or equivalent,
- these functions will take effect at statement compilation/execution
- time when a literal value is passed, as in::
-
- # bound-value handling of MyStringType will be applied to the
- # literal value "some string"
- stmt = select(type_coerce("some string", MyStringType))
-
- When using :func:`.type_coerce` with composed expressions, note that
- **parenthesis are not applied**. If :func:`.type_coerce` is being
- used in an operator context where the parenthesis normally present from
- CAST are necessary, use the :meth:`.TypeCoerce.self_group` method::
-
- >>> some_integer = column("someint", Integer)
- >>> some_string = column("somestr", String)
- >>> expr = type_coerce(some_integer + 5, String) + some_string
- >>> print(expr)
- someint + :someint_1 || somestr
- >>> expr = type_coerce(some_integer + 5, String).self_group() + some_string
- >>> print(expr)
- (someint + :someint_1) || somestr
-
- :param expression: A SQL expression, such as a
- :class:`_expression.ColumnElement`
- expression or a Python string which will be coerced into a bound
- literal value.
-
- :param type\_: A :class:`.TypeEngine` class or instance indicating
- the type to which the expression is coerced.
-
- .. seealso::
-
- :ref:`coretutorial_casts`
-
- :func:`.cast`
-
- """ # noqa
self.type = type_api.to_instance(type_)
self.clause = coercions.expect(
roles.ExpressionElementRole,
return self
-class Extract(ColumnElement):
+class Extract(ColumnElement[_T]):
"""Represent a SQL EXTRACT clause, ``extract(field FROM expr)``."""
__visit_name__ = "extract"
("field", InternalTraversal.dp_string),
]
- def __init__(self, field, expr, **kwargs):
- """Return a :class:`.Extract` construct.
-
- This is typically available as :func:`.extract`
- as well as ``func.extract`` from the
- :data:`.func` namespace.
-
- :param field: The field to extract.
-
- :param expr: A column or Python scalar expression serving as the
- right side of the ``EXTRACT`` expression.
-
- E.g.::
-
- from sqlalchemy import extract
- from sqlalchemy import table, column
-
- logged_table = table("user",
- column("id"),
- column("date_created"),
- )
-
- stmt = select(logged_table.c.id).where(
- extract("YEAR", logged_table.c.date_created) == 2021
- )
-
- In the above example, the statement is used to select ids from the
- database where the ``YEAR`` component matches a specific value.
-
- Similarly, one can also select an extracted component::
-
- stmt = select(
- extract("YEAR", logged_table.c.date_created)
- ).where(logged_table.c.id == 1)
-
- The implementation of ``EXTRACT`` may vary across database backends.
- Users are reminded to consult their database documentation.
- """
+ def __init__(self, field, expr):
self.type = type_api.INTEGERTYPE
self.field = field
self.expr = coercions.expect(roles.ExpressionElementRole, expr)
@util.memoized_property
def _text_clause(self):
- return TextClause._create_text(self.element)
+ return TextClause(self.element)
-class UnaryExpression(ColumnElement):
+class UnaryExpression(ColumnElement[_T]):
"""Define a 'unary' expression.
A unary expression has a single column expression
element,
operator=None,
modifier=None,
- type_=None,
+ type_: Union[Type["TypeEngine[_T]"], "TypeEngine[_T]"] = None,
wraps_column_expression=False,
):
self.operator = operator
self.element = element.self_group(
against=self.operator or self.modifier
)
- self.type = type_api.to_instance(type_)
+ self.type: TypeEngine[_T] = type_api.to_instance(type_)
self.wraps_column_expression = wraps_column_expression
@classmethod
def _create_nulls_first(cls, column):
- """Produce the ``NULLS FIRST`` modifier for an ``ORDER BY`` expression.
-
- :func:`.nulls_first` is intended to modify the expression produced
- by :func:`.asc` or :func:`.desc`, and indicates how NULL values
- should be handled when they are encountered during ordering::
-
-
- from sqlalchemy import desc, nulls_first
-
- stmt = select(users_table).order_by(
- nulls_first(desc(users_table.c.name)))
-
- The SQL expression from the above would resemble::
-
- SELECT id, name FROM user ORDER BY name DESC NULLS FIRST
-
- Like :func:`.asc` and :func:`.desc`, :func:`.nulls_first` is typically
- invoked from the column expression itself using
- :meth:`_expression.ColumnElement.nulls_first`,
- rather than as its standalone
- function version, as in::
-
- stmt = select(users_table).order_by(
- users_table.c.name.desc().nulls_first())
-
- .. versionchanged:: 1.4 :func:`.nulls_first` is renamed from
- :func:`.nullsfirst` in previous releases.
- The previous name remains available for backwards compatibility.
-
- .. seealso::
-
- :func:`.asc`
-
- :func:`.desc`
-
- :func:`.nulls_last`
-
- :meth:`_expression.Select.order_by`
-
- """
return UnaryExpression(
coercions.expect(roles.ByOfRole, column),
modifier=operators.nulls_first_op,
@classmethod
def _create_nulls_last(cls, column):
- """Produce the ``NULLS LAST`` modifier for an ``ORDER BY`` expression.
-
- :func:`.nulls_last` is intended to modify the expression produced
- by :func:`.asc` or :func:`.desc`, and indicates how NULL values
- should be handled when they are encountered during ordering::
-
-
- from sqlalchemy import desc, nulls_last
-
- stmt = select(users_table).order_by(
- nulls_last(desc(users_table.c.name)))
-
- The SQL expression from the above would resemble::
-
- SELECT id, name FROM user ORDER BY name DESC NULLS LAST
-
- Like :func:`.asc` and :func:`.desc`, :func:`.nulls_last` is typically
- invoked from the column expression itself using
- :meth:`_expression.ColumnElement.nulls_last`,
- rather than as its standalone
- function version, as in::
-
- stmt = select(users_table).order_by(
- users_table.c.name.desc().nulls_last())
-
- .. versionchanged:: 1.4 :func:`.nulls_last` is renamed from
- :func:`.nullslast` in previous releases.
- The previous name remains available for backwards compatibility.
-
- .. seealso::
-
- :func:`.asc`
-
- :func:`.desc`
-
- :func:`.nulls_first`
-
- :meth:`_expression.Select.order_by`
-
- """
return UnaryExpression(
coercions.expect(roles.ByOfRole, column),
modifier=operators.nulls_last_op,
@classmethod
def _create_desc(cls, column):
- """Produce a descending ``ORDER BY`` clause element.
-
- e.g.::
-
- from sqlalchemy import desc
-
- stmt = select(users_table).order_by(desc(users_table.c.name))
-
- will produce SQL as::
-
- SELECT id, name FROM user ORDER BY name DESC
-
- The :func:`.desc` function is a standalone version of the
- :meth:`_expression.ColumnElement.desc`
- method available on all SQL expressions,
- e.g.::
-
-
- stmt = select(users_table).order_by(users_table.c.name.desc())
-
- :param column: A :class:`_expression.ColumnElement` (e.g.
- scalar SQL expression)
- with which to apply the :func:`.desc` operation.
-
- .. seealso::
-
- :func:`.asc`
-
- :func:`.nulls_first`
-
- :func:`.nulls_last`
-
- :meth:`_expression.Select.order_by`
-
- """
return UnaryExpression(
coercions.expect(roles.ByOfRole, column),
modifier=operators.desc_op,
@classmethod
def _create_asc(cls, column):
- """Produce an ascending ``ORDER BY`` clause element.
-
- e.g.::
-
- from sqlalchemy import asc
- stmt = select(users_table).order_by(asc(users_table.c.name))
-
- will produce SQL as::
-
- SELECT id, name FROM user ORDER BY name ASC
-
- The :func:`.asc` function is a standalone version of the
- :meth:`_expression.ColumnElement.asc`
- method available on all SQL expressions,
- e.g.::
-
-
- stmt = select(users_table).order_by(users_table.c.name.asc())
-
- :param column: A :class:`_expression.ColumnElement` (e.g.
- scalar SQL expression)
- with which to apply the :func:`.asc` operation.
-
- .. seealso::
-
- :func:`.desc`
-
- :func:`.nulls_first`
-
- :func:`.nulls_last`
-
- :meth:`_expression.Select.order_by`
-
- """
return UnaryExpression(
coercions.expect(roles.ByOfRole, column),
modifier=operators.asc_op,
@classmethod
def _create_distinct(cls, expr):
- """Produce an column-expression-level unary ``DISTINCT`` clause.
-
- This applies the ``DISTINCT`` keyword to an individual column
- expression, and is typically contained within an aggregate function,
- as in::
-
- from sqlalchemy import distinct, func
- stmt = select(func.count(distinct(users_table.c.name)))
-
- The above would produce an expression resembling::
-
- SELECT COUNT(DISTINCT name) FROM user
-
- The :func:`.distinct` function is also available as a column-level
- method, e.g. :meth:`_expression.ColumnElement.distinct`, as in::
-
- stmt = select(func.count(users_table.c.name.distinct()))
-
- The :func:`.distinct` operator is different from the
- :meth:`_expression.Select.distinct` method of
- :class:`_expression.Select`,
- which produces a ``SELECT`` statement
- with ``DISTINCT`` applied to the result set as a whole,
- e.g. a ``SELECT DISTINCT`` expression. See that method for further
- information.
-
- .. seealso::
-
- :meth:`_expression.ColumnElement.distinct`
-
- :meth:`_expression.Select.distinct`
-
- :data:`.func`
-
- """
expr = coercions.expect(roles.ExpressionElementRole, expr)
return UnaryExpression(
expr,
@classmethod
def _create_any(cls, expr):
- """Produce an ANY expression.
-
- For dialects such as that of PostgreSQL, this operator applies
- to usage of the :class:`_types.ARRAY` datatype, for that of
- MySQL, it may apply to a subquery. e.g.::
-
- # renders on PostgreSQL:
- # '5 = ANY (somearray)'
- expr = 5 == any_(mytable.c.somearray)
-
- # renders on MySQL:
- # '5 = ANY (SELECT value FROM table)'
- expr = 5 == any_(select(table.c.value))
-
- Comparison to NULL may work using ``None`` or :func:`_sql.null`::
-
- None == any_(mytable.c.somearray)
-
- The any_() / all_() operators also feature a special "operand flipping"
- behavior such that if any_() / all_() are used on the left side of a
- comparison using a standalone operator such as ``==``, ``!=``, etc.
- (not including operator methods such as
- :meth:`_sql.ColumnOperators.is_`) the rendered expression is flipped::
-
- # would render '5 = ANY (column)`
- any_(mytable.c.column) == 5
-
- Or with ``None``, which note will not perform
- the usual step of rendering "IS" as is normally the case for NULL::
-
- # would render 'NULL = ANY(somearray)'
- any_(mytable.c.somearray) == None
-
- .. versionchanged:: 1.4.26 repaired the use of any_() / all_()
- comparing to NULL on the right side to be flipped to the left.
-
- The column-level :meth:`_sql.ColumnElement.any_` method (not to be
- confused with :class:`_types.ARRAY` level
- :meth:`_types.ARRAY.Comparator.any`) is shorthand for
- ``any_(col)``::
-
- 5 = mytable.c.somearray.any_()
-
- .. seealso::
-
- :meth:`_sql.ColumnOperators.any_`
-
- :func:`_expression.all_`
-
- """
-
expr = coercions.expect(roles.ExpressionElementRole, expr)
expr = expr.self_group()
@classmethod
def _create_all(cls, expr):
- """Produce an ALL expression.
-
- For dialects such as that of PostgreSQL, this operator applies
- to usage of the :class:`_types.ARRAY` datatype, for that of
- MySQL, it may apply to a subquery. e.g.::
-
- # renders on PostgreSQL:
- # '5 = ALL (somearray)'
- expr = 5 == all_(mytable.c.somearray)
-
- # renders on MySQL:
- # '5 = ALL (SELECT value FROM table)'
- expr = 5 == all_(select(table.c.value))
-
- Comparison to NULL may work using ``None``::
-
- None == all_(mytable.c.somearray)
-
- The any_() / all_() operators also feature a special "operand flipping"
- behavior such that if any_() / all_() are used on the left side of a
- comparison using a standalone operator such as ``==``, ``!=``, etc.
- (not including operator methods such as
- :meth:`_sql.ColumnOperators.is_`) the rendered expression is flipped::
-
- # would render '5 = ALL (column)`
- all_(mytable.c.column) == 5
-
- Or with ``None``, which note will not perform
- the usual step of rendering "IS" as is normally the case for NULL::
-
- # would render 'NULL = ALL(somearray)'
- all_(mytable.c.somearray) == None
-
- .. versionchanged:: 1.4.26 repaired the use of any_() / all_()
- comparing to NULL on the right side to be flipped to the left.
-
- The column-level :meth:`_sql.ColumnElement.all_` method (not to be
- confused with :class:`_types.ARRAY` level
- :meth:`_types.ARRAY.Comparator.all`) is shorthand for
- ``all_(col)``::
-
- 5 == mytable.c.somearray.all_()
-
- .. seealso::
-
- :meth:`_sql.ColumnOperators.all_`
-
- :func:`_expression.any_`
-
- """
expr = coercions.expect(roles.ExpressionElementRole, expr)
expr = expr.self_group()
return CollectionAggregate(
return AsBoolean(self.element, self.negate, self.operator)
-class BinaryExpression(ColumnElement):
+class BinaryExpression(ColumnElement[_T]):
"""Represent an expression that is ``LEFT <operator> RIGHT``.
A :class:`.BinaryExpression` is generated automatically
"""
def __init__(
- self, left, right, operator, type_=None, negate=None, modifiers=None
+ self,
+ left: ColumnElement,
+ right: Union[ColumnElement, ClauseList],
+ operator,
+ type_: Optional[
+ Union[Type["TypeEngine[_T]"], "TypeEngine[_T]"]
+ ] = None,
+ negate=None,
+ modifiers=None,
):
# allow compatibility with libraries that
# refer to BinaryExpression directly and pass strings
self.left = left.self_group(against=operator)
self.right = right.self_group(against=operator)
self.operator = operator
- self.type = type_api.to_instance(type_)
+ self.type: TypeEngine[_T] = type_api.to_instance(type_)
self.negate = negate
self._is_implicitly_boolean = operators.is_boolean(operator)
__nonzero__ = __bool__
+ if typing.TYPE_CHECKING:
+
+ def __invert__(
+ self: "BinaryExpression[_T]",
+ ) -> "BinaryExpression[_T]":
+ ...
+
@property
def is_comparison(self):
return operators.is_comparison(self.operator)
RANGE_CURRENT = util.symbol("RANGE_CURRENT")
-class Over(ColumnElement):
+class Over(ColumnElement[_T]):
"""Represent an OVER clause.
This is a special operator against a so-called
def __init__(
self, element, partition_by=None, order_by=None, range_=None, rows=None
):
- r"""Produce an :class:`.Over` object against a function.
-
- Used against aggregate or so-called "window" functions,
- for database backends that support window functions.
-
- :func:`_expression.over` is usually called using
- the :meth:`.FunctionElement.over` method, e.g.::
-
- func.row_number().over(order_by=mytable.c.some_column)
-
- Would produce::
-
- ROW_NUMBER() OVER(ORDER BY some_column)
-
- Ranges are also possible using the :paramref:`.expression.over.range_`
- and :paramref:`.expression.over.rows` parameters. These
- mutually-exclusive parameters each accept a 2-tuple, which contains
- a combination of integers and None::
-
- func.row_number().over(
- order_by=my_table.c.some_column, range_=(None, 0))
-
- The above would produce::
-
- ROW_NUMBER() OVER(ORDER BY some_column
- RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)
-
- A value of ``None`` indicates "unbounded", a
- value of zero indicates "current row", and negative / positive
- integers indicate "preceding" and "following":
-
- * RANGE BETWEEN 5 PRECEDING AND 10 FOLLOWING::
-
- func.row_number().over(order_by='x', range_=(-5, 10))
-
- * ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW::
-
- func.row_number().over(order_by='x', rows=(None, 0))
-
- * RANGE BETWEEN 2 PRECEDING AND UNBOUNDED FOLLOWING::
-
- func.row_number().over(order_by='x', range_=(-2, None))
-
- * RANGE BETWEEN 1 FOLLOWING AND 3 FOLLOWING::
-
- func.row_number().over(order_by='x', range_=(1, 3))
-
- .. versionadded:: 1.1 support for RANGE / ROWS within a window
-
-
- :param element: a :class:`.FunctionElement`, :class:`.WithinGroup`,
- or other compatible construct.
- :param partition_by: a column element or string, or a list
- of such, that will be used as the PARTITION BY clause
- of the OVER construct.
- :param order_by: a column element or string, or a list
- of such, that will be used as the ORDER BY clause
- of the OVER construct.
- :param range\_: optional range clause for the window. This is a
- tuple value which can contain integer values or ``None``,
- and will render a RANGE BETWEEN PRECEDING / FOLLOWING clause.
-
- .. versionadded:: 1.1
-
- :param rows: optional rows clause for the window. This is a tuple
- value which can contain integer values or None, and will render
- a ROWS BETWEEN PRECEDING / FOLLOWING clause.
-
- .. versionadded:: 1.1
-
- This function is also available from the :data:`~.expression.func`
- construct itself via the :meth:`.FunctionElement.over` method.
-
- .. seealso::
-
- :ref:`tutorial_window_functions` - in the :ref:`unified_tutorial`
-
- :data:`.expression.func`
-
- :func:`_expression.within_group`
-
- """
self.element = element
if order_by is not None:
self.order_by = ClauseList(
)
-class WithinGroup(ColumnElement):
+class WithinGroup(ColumnElement[_T]):
"""Represent a WITHIN GROUP (ORDER BY) clause.
This is a special operator against so-called
order_by = None
def __init__(self, element, *order_by):
- r"""Produce a :class:`.WithinGroup` object against a function.
-
- Used against so-called "ordered set aggregate" and "hypothetical
- set aggregate" functions, including :class:`.percentile_cont`,
- :class:`.rank`, :class:`.dense_rank`, etc.
-
- :func:`_expression.within_group` is usually called using
- the :meth:`.FunctionElement.within_group` method, e.g.::
-
- from sqlalchemy import within_group
- stmt = select(
- department.c.id,
- func.percentile_cont(0.5).within_group(
- department.c.salary.desc()
- )
- )
-
- The above statement would produce SQL similar to
- ``SELECT department.id, percentile_cont(0.5)
- WITHIN GROUP (ORDER BY department.salary DESC)``.
-
- :param element: a :class:`.FunctionElement` construct, typically
- generated by :data:`~.expression.func`.
- :param \*order_by: one or more column elements that will be used
- as the ORDER BY clause of the WITHIN GROUP construct.
-
- .. versionadded:: 1.1
-
- .. seealso::
-
- :ref:`tutorial_functions_within_group` - in the
- :ref:`unified_tutorial`
-
- :data:`.expression.func`
-
- :func:`_expression.over`
-
- """
self.element = element
if order_by is not None:
self.order_by = ClauseList(
criterion = None
def __init__(self, func, *criterion):
- """Produce a :class:`.FunctionFilter` object against a function.
-
- Used against aggregate and window functions,
- for database backends that support the "FILTER" clause.
-
- E.g.::
-
- from sqlalchemy import funcfilter
- funcfilter(func.count(1), MyClass.name == 'some name')
-
- Would produce "COUNT(1) FILTER (WHERE myclass.name = 'some name')".
-
- This function is also available from the :data:`~.expression.func`
- construct itself via the :meth:`.FunctionElement.filter` method.
-
- .. versionadded:: 1.0.0
-
- .. seealso::
-
- :ref:`tutorial_functions_within_group` - in the
- :ref:`unified_tutorial`
-
- :meth:`.FunctionElement.filter`
-
- """
self.func = func
self.filter(*criterion)
)
-class Label(roles.LabeledColumnExprRole, ColumnElement):
+class Label(roles.LabeledColumnExprRole, ColumnElement[_T]):
"""Represents a column label (AS).
Represent a label, as typically applied to any column-level
]
def __init__(self, name, element, type_=None):
- """Return a :class:`Label` object for the
- given :class:`_expression.ColumnElement`.
-
- A label changes the name of an element in the columns clause of a
- ``SELECT`` statement, typically via the ``AS`` SQL keyword.
-
- This functionality is more conveniently available via the
- :meth:`_expression.ColumnElement.label` method on
- :class:`_expression.ColumnElement`.
-
- :param name: label name
-
- :param obj: a :class:`_expression.ColumnElement`.
-
- """
-
orig_element = element
element = coercions.expect(
roles.ExpressionElementRole,
return self.key, e
-class NamedColumn(ColumnElement):
+class NamedColumn(ColumnElement[_T]):
is_literal = False
table = None
roles.LabeledColumnExprRole,
roles.StrAsPlainColumnRole,
Immutable,
- NamedColumn,
+ NamedColumn[_T],
):
"""Represents a column expression from any textual string.
_is_multiparam_column = False
- def __init__(self, text, type_=None, is_literal=False, _selectable=None):
- """Produce a :class:`.ColumnClause` object.
-
- The :class:`.ColumnClause` is a lightweight analogue to the
- :class:`_schema.Column` class. The :func:`_expression.column`
- function can
- be invoked with just a name alone, as in::
-
- from sqlalchemy import column
-
- id, name = column("id"), column("name")
- stmt = select(id, name).select_from("user")
-
- The above statement would produce SQL like::
-
- SELECT id, name FROM user
-
- Once constructed, :func:`_expression.column`
- may be used like any other SQL
- expression element such as within :func:`_expression.select`
- constructs::
-
- from sqlalchemy.sql import column
-
- id, name = column("id"), column("name")
- stmt = select(id, name).select_from("user")
-
- The text handled by :func:`_expression.column`
- is assumed to be handled
- like the name of a database column; if the string contains mixed case,
- special characters, or matches a known reserved word on the target
- backend, the column expression will render using the quoting
- behavior determined by the backend. To produce a textual SQL
- expression that is rendered exactly without any quoting,
- use :func:`_expression.literal_column` instead,
- or pass ``True`` as the
- value of :paramref:`_expression.column.is_literal`. Additionally,
- full SQL
- statements are best handled using the :func:`_expression.text`
- construct.
-
- :func:`_expression.column` can be used in a table-like
- fashion by combining it with the :func:`.table` function
- (which is the lightweight analogue to :class:`_schema.Table`
- ) to produce
- a working table construct with minimal boilerplate::
-
- from sqlalchemy import table, column, select
-
- user = table("user",
- column("id"),
- column("name"),
- column("description"),
- )
-
- stmt = select(user.c.description).where(user.c.name == 'wendy')
-
- A :func:`_expression.column` / :func:`.table`
- construct like that illustrated
- above can be created in an
- ad-hoc fashion and is not associated with any
- :class:`_schema.MetaData`, DDL, or events, unlike its
- :class:`_schema.Table` counterpart.
-
- .. versionchanged:: 1.0.0 :func:`_expression.column` can now
- be imported from the plain ``sqlalchemy`` namespace like any
- other SQL element.
-
- :param text: the text of the element.
-
- :param type: :class:`_types.TypeEngine` object which can associate
- this :class:`.ColumnClause` with a type.
-
- :param is_literal: if True, the :class:`.ColumnClause` is assumed to
- be an exact expression that will be delivered to the output with no
- quoting rules applied regardless of case sensitive settings. the
- :func:`_expression.literal_column()` function essentially invokes
- :func:`_expression.column` while passing ``is_literal=True``.
-
- .. seealso::
-
- :class:`_schema.Column`
-
- :func:`_expression.literal_column`
-
- :func:`.table`
-
- :func:`_expression.text`
-
- :ref:`sqlexpression_literal_column`
-
- """
+ def __init__(
+ self,
+ text: str,
+ type_: Optional[
+ Union[Type["TypeEngine[_T]"], "TypeEngine[_T]"]
+ ] = None,
+ is_literal: bool = False,
+ _selectable: Optional["FromClause"] = None,
+ ):
self.key = self.name = text
self.table = _selectable
- self.type = type_api.to_instance(type_)
+ self.type: TypeEngine[_T] = type_api.to_instance(type_)
self.is_literal = is_literal
def get_children(self, column_tables=False, **kw):
_traverse_internals = [("collation", InternalTraversal.dp_string)]
+ @classmethod
+ def _create_collation_expression(cls, expression, collation):
+ expr = coercions.expect(roles.ExpressionElementRole, expression)
+ return BinaryExpression(
+ expr,
+ CollationClause(collation),
+ operators.collate,
+ type_=expression.type,
+ )
+
def __init__(self, collation):
self.collation = collation
@classmethod
def safe_construct(
cls, seed, body, enclosing_label=None, sanitize_key=False
- ):
+ ) -> "_anonymous_label":
if sanitize_key:
body = re.sub(r"[%\(\) \$]+", "_", body).strip("_")
"""
-__all__ = [
- "Alias",
- "AliasedReturnsRows",
- "any_",
- "all_",
- "CacheKey",
- "ClauseElement",
- "ColumnCollection",
- "ColumnElement",
- "CompoundSelect",
- "Delete",
- "FromClause",
- "Insert",
- "Join",
- "Lateral",
- "LambdaElement",
- "StatementLambdaElement",
- "Select",
- "Selectable",
- "TableClause",
- "TableValuedAlias",
- "Update",
- "Values",
- "alias",
- "and_",
- "asc",
- "between",
- "bindparam",
- "case",
- "cast",
- "column",
- "custom_op",
- "cte",
- "delete",
- "desc",
- "distinct",
- "except_",
- "except_all",
- "exists",
- "extract",
- "func",
- "modifier",
- "collate",
- "insert",
- "intersect",
- "intersect_all",
- "join",
- "label",
- "lateral",
- "lambda_stmt",
- "literal",
- "literal_column",
- "not_",
- "null",
- "nulls_first",
- "nulls_last",
- "or_",
- "outparam",
- "outerjoin",
- "over",
- "select",
- "table",
- "text",
- "tuple_",
- "type_coerce",
- "quoted_name",
- "union",
- "union_all",
- "update",
- "quoted_name",
- "within_group",
- "Subquery",
- "TableSample",
- "tablesample",
- "values",
-]
+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 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 tuple_ as tuple_
+from ._elements_constructors import type_coerce as type_coerce
+from ._elements_constructors import typing as typing
+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 .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 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 TextClause as TextClause
+from .elements import True_ as True_
+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_NONE as LABEL_STYLE_NONE
+from .selectable import Lateral as Lateral
+from .selectable import ReturnsRows as ReturnsRows
+from .selectable import ScalarSelect as ScalarSelect
+from .selectable import Select as Select
+from .selectable import Selectable as Selectable
+from .selectable import SelectBase as SelectBase
+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
-from typing import Callable
+if True:
+ # work around zimports
+ from .selectable import (
+ LABEL_STYLE_DISAMBIGUATE_ONLY as LABEL_STYLE_DISAMBIGUATE_ONLY,
+ )
+ from .selectable import (
+ LABEL_STYLE_TABLENAME_PLUS_COL as LABEL_STYLE_TABLENAME_PLUS_COL,
+ )
-from .base import _from_objects
-from .base import _select_iterables
-from .base import ColumnCollection
-from .base import Executable
-from .cache_key import CacheKey
-from .dml import Delete
-from .dml import Insert
-from .dml import Update
-from .dml import UpdateBase
-from .dml import ValuesBase
-from .elements import _truncated_label
-from .elements import between
-from .elements import BinaryExpression
-from .elements import BindParameter
-from .elements import BooleanClauseList
-from .elements import Case
-from .elements import Cast
-from .elements import ClauseElement
-from .elements import ClauseList
-from .elements import collate
-from .elements import CollectionAggregate
-from .elements import ColumnClause
-from .elements import ColumnElement
-from .elements import Extract
-from .elements import False_
-from .elements import FunctionFilter
-from .elements import Grouping
-from .elements import Label
-from .elements import literal
-from .elements import literal_column
-from .elements import not_
-from .elements import Null
-from .elements import outparam
-from .elements import Over
-from .elements import quoted_name
-from .elements import ReleaseSavepointClause
-from .elements import RollbackToSavepointClause
-from .elements import SavepointClause
-from .elements import TextClause
-from .elements import True_
-from .elements import Tuple
-from .elements import TypeClause
-from .elements import TypeCoerce
-from .elements import UnaryExpression
-from .elements import WithinGroup
-from .functions import func
-from .functions import Function
-from .functions import FunctionElement
-from .functions import modifier
-from .lambdas import lambda_stmt
-from .lambdas import LambdaElement
-from .lambdas import StatementLambdaElement
-from .operators import ColumnOperators
-from .operators import custom_op
-from .operators import Operators
-from .selectable import Alias
-from .selectable import AliasedReturnsRows
-from .selectable import CompoundSelect
-from .selectable import CTE
-from .selectable import Exists
-from .selectable import FromClause
-from .selectable import FromGrouping
-from .selectable import GenerativeSelect
-from .selectable import HasCTE
-from .selectable import HasPrefixes
-from .selectable import HasSuffixes
-from .selectable import Join
-from .selectable import LABEL_STYLE_DEFAULT
-from .selectable import LABEL_STYLE_DISAMBIGUATE_ONLY
-from .selectable import LABEL_STYLE_NONE
-from .selectable import LABEL_STYLE_TABLENAME_PLUS_COL
-from .selectable import Lateral
-from .selectable import ReturnsRows
-from .selectable import ScalarSelect
-from .selectable import Select
-from .selectable import Selectable
-from .selectable import SelectBase
-from .selectable import Subquery
-from .selectable import TableClause
-from .selectable import TableSample
-from .selectable import TableValuedAlias
-from .selectable import TextAsFrom
-from .selectable import TextualSelect
-from .selectable import Values
-from .visitors import Visitable
-from ..util.langhelpers import public_factory
-
-# TODO: proposal is to remove public_factory and replace with traditional
-# functions exported here.
-
-all_ = public_factory(CollectionAggregate._create_all, ".sql.expression.all_")
-any_ = public_factory(CollectionAggregate._create_any, ".sql.expression.any_")
-and_ = public_factory(BooleanClauseList.and_, ".sql.expression.and_")
-alias = public_factory(Alias._factory, ".sql.expression.alias")
-tablesample = public_factory(
- TableSample._factory, ".sql.expression.tablesample"
-)
-lateral = public_factory(Lateral._factory, ".sql.expression.lateral")
-or_ = public_factory(BooleanClauseList.or_, ".sql.expression.or_")
-bindparam = public_factory(BindParameter, ".sql.expression.bindparam")
-select = public_factory(Select._create, ".sql.expression.select")
-text = public_factory(TextClause._create_text, ".sql.expression.text")
-table = public_factory(TableClause, ".sql.expression.table")
-column = public_factory(ColumnClause, ".sql.expression.column")
-over = public_factory(Over, ".sql.expression.over")
-within_group = public_factory(WithinGroup, ".sql.expression.within_group")
-label = public_factory(Label, ".sql.expression.label")
-case = public_factory(Case, ".sql.expression.case")
-cast = public_factory(Cast, ".sql.expression.cast")
-cte = public_factory(CTE._factory, ".sql.expression.cte")
-values = public_factory(Values, ".sql.expression.values")
-extract = public_factory(Extract, ".sql.expression.extract")
-tuple_ = public_factory(Tuple, ".sql.expression.tuple_")
-except_ = public_factory(
- CompoundSelect._create_except, ".sql.expression.except_"
-)
-except_all = public_factory(
- CompoundSelect._create_except_all, ".sql.expression.except_all"
-)
-intersect = public_factory(
- CompoundSelect._create_intersect, ".sql.expression.intersect"
-)
-intersect_all = public_factory(
- CompoundSelect._create_intersect_all, ".sql.expression.intersect_all"
-)
-union = public_factory(CompoundSelect._create_union, ".sql.expression.union")
-union_all = public_factory(
- CompoundSelect._create_union_all, ".sql.expression.union_all"
-)
-exists = public_factory(Exists, ".sql.expression.exists")
-nulls_first = public_factory(
- UnaryExpression._create_nulls_first, ".sql.expression.nulls_first"
-)
-nullsfirst = nulls_first # deprecated 1.4; see #5435
-nulls_last = public_factory(
- UnaryExpression._create_nulls_last, ".sql.expression.nulls_last"
-)
-nullslast = nulls_last # deprecated 1.4; see #5435
-asc = public_factory(UnaryExpression._create_asc, ".sql.expression.asc")
-desc = public_factory(UnaryExpression._create_desc, ".sql.expression.desc")
-distinct = public_factory(
- UnaryExpression._create_distinct, ".sql.expression.distinct"
-)
-type_coerce = public_factory(TypeCoerce, ".sql.expression.type_coerce")
-true = public_factory(True_._instance, ".sql.expression.true")
-false = public_factory(False_._instance, ".sql.expression.false")
-null = public_factory(Null._instance, ".sql.expression.null")
-join = public_factory(Join._create_join, ".sql.expression.join")
-outerjoin = public_factory(Join._create_outerjoin, ".sql.expression.outerjoin")
-insert = public_factory(Insert, ".sql.expression.insert")
-update = public_factory(Update, ".sql.expression.update")
-delete = public_factory(Delete, ".sql.expression.delete")
-funcfilter = public_factory(FunctionFilter, ".sql.expression.funcfilter")
-
-
-# internal functions still being called from tests and the ORM,
-# these might be better off in some other namespace
-
-
-# old names for compatibility
-_Executable = Executable
-_BindParamClause = BindParameter
-_Label = Label
-_SelectBase = SelectBase
-_BinaryExpression = BinaryExpression
-_Cast = Cast
-_Null = Null
-_False = False_
-_True = True_
-_TextClause = TextClause
-_UnaryExpression = UnaryExpression
-_Case = Case
-_Tuple = Tuple
-_Over = Over
-_TypeClause = TypeClause
-_Extract = Extract
-_Exists = Exists
-_Grouping = Grouping
-_FromGrouping = FromGrouping
-_ScalarSelect = ScalarSelect
+nullsfirst = nulls_first
+nullslast = nulls_last
s = select(function_element)
"""
- s = Select._create(self)
+ s = Select(self)
if self._execution_options:
s = s.execution_options(**self._execution_options)
return s
"""Defines operators used in SQL expressions."""
-from operator import add
-from operator import and_
-from operator import contains
-from operator import eq
-from operator import floordiv
-from operator import ge
-from operator import getitem
-from operator import gt
-from operator import inv
-from operator import le
-from operator import lshift
-from operator import lt
-from operator import mod
-from operator import mul
-from operator import ne
-from operator import neg
-from operator import or_
-from operator import rshift
-from operator import sub
-from operator import truediv
+from operator import add as _uncast_add
+from operator import and_ as _uncast_and_
+from operator import contains as _uncast_contains
+from operator import eq as _uncast_eq
+from operator import floordiv as _uncast_floordiv
+from operator import ge as _uncast_ge
+from operator import getitem as _uncast_getitem
+from operator import gt as _uncast_gt
+from operator import inv as _uncast_inv
+from operator import le as _uncast_le
+from operator import lshift as _uncast_lshift
+from operator import lt as _uncast_lt
+from operator import mod as _uncast_mod
+from operator import mul as _uncast_mul
+from operator import ne as _uncast_ne
+from operator import neg as _uncast_neg
+from operator import or_ as _uncast_or_
+from operator import rshift as _uncast_rshift
+from operator import sub as _uncast_sub
+from operator import truediv as _uncast_truediv
+import typing
+from typing import Any
+from typing import Callable
+from typing import cast
+from typing import Generic
+from typing import Optional
+from typing import overload
+from typing import Type
+from typing import TypeVar
+from typing import Union
from .. import exc
from .. import util
-
-
-class Operators:
+from ..util.typing import Protocol
+
+if typing.TYPE_CHECKING:
+ from .elements import BinaryExpression
+ from .elements import ColumnElement
+ from .type_api import TypeEngine
+
+_OP_RETURN = TypeVar("_OP_RETURN", bound=Any, covariant=True)
+_T = TypeVar("_T", bound=Any)
+
+
+class OperatorType(Protocol):
+ """describe an op() function."""
+
+ __name__: str
+
+ def __call__(
+ self, left: "Operators[_OP_RETURN]", *other: Any, **kwargs: Any
+ ) -> "_OP_RETURN":
+ ...
+
+
+add = cast(OperatorType, _uncast_add)
+and_ = cast(OperatorType, _uncast_and_)
+contains = cast(OperatorType, _uncast_contains)
+eq = cast(OperatorType, _uncast_eq)
+floordiv = cast(OperatorType, _uncast_floordiv)
+ge = cast(OperatorType, _uncast_ge)
+getitem = cast(OperatorType, _uncast_getitem)
+gt = cast(OperatorType, _uncast_gt)
+inv = cast(OperatorType, _uncast_inv)
+le = cast(OperatorType, _uncast_le)
+lshift = cast(OperatorType, _uncast_lshift)
+lt = cast(OperatorType, _uncast_lt)
+mod = cast(OperatorType, _uncast_mod)
+mul = cast(OperatorType, _uncast_mul)
+ne = cast(OperatorType, _uncast_ne)
+neg = cast(OperatorType, _uncast_neg)
+or_ = cast(OperatorType, _uncast_or_)
+rshift = cast(OperatorType, _uncast_rshift)
+sub = cast(OperatorType, _uncast_sub)
+truediv = cast(OperatorType, _uncast_truediv)
+
+
+class Operators(Generic[_OP_RETURN]):
"""Base of comparison and logical operators.
Implements base methods
__slots__ = ()
- def __and__(self, other):
+ def __and__(self, other: Any) -> "Operators":
"""Implement the ``&`` operator.
When used with SQL expressions, results in an
"""
return self.operate(and_, other)
- def __or__(self, other):
+ def __or__(self, other: Any) -> "Operators":
"""Implement the ``|`` operator.
When used with SQL expressions, results in an
"""
return self.operate(or_, other)
- def __invert__(self):
+ def __invert__(self) -> "Operators":
"""Implement the ``~`` operator.
When used with SQL expressions, results in a
def op(
self,
- opstring,
- precedence=0,
- is_comparison=False,
- return_type=None,
+ opstring: Any,
+ precedence: int = 0,
+ is_comparison: bool = False,
+ return_type: Optional[
+ Union[Type["TypeEngine[_T]"], "TypeEngine[_T]"]
+ ] = None,
python_impl=None,
- ):
+ ) -> Callable[[Any], _OP_RETURN]:
"""Produce a generic operator function.
e.g.::
python_impl=python_impl,
)
- def against(other):
+ def against(other: Any) -> _OP_RETURN:
return operator(self, other)
return against
- def bool_op(self, opstring, precedence=0, python_impl=None):
+ def bool_op(
+ self, opstring: Any, precedence: int = 0, python_impl=None
+ ) -> Callable[[Any], _OP_RETURN]:
"""Return a custom boolean operator.
This method is shorthand for calling
python_impl=python_impl,
)
- def operate(self, op, *other, **kwargs):
+ def operate(
+ self, op: OperatorType, *other: Any, **kwargs: Any
+ ) -> _OP_RETURN:
r"""Operate on an argument.
This is the lowest level of operation, raises
__sa_operate__ = operate
- def reverse_operate(self, op, other, **kwargs):
+ def reverse_operate(
+ self, op: OperatorType, other: Any, **kwargs: Any
+ ) -> _OP_RETURN:
"""Reverse operate on an argument.
Usage is the same as :meth:`operate`.
raise NotImplementedError(str(op))
-class custom_op:
+class custom_op(OperatorType, Generic[_T]):
"""Represent a 'custom' operator.
:class:`.custom_op` is normally instantiated when the
def __init__(
self,
- opstring,
- precedence=0,
- is_comparison=False,
- return_type=None,
- natural_self_precedent=False,
- eager_grouping=False,
+ opstring: str,
+ precedence: int = 0,
+ is_comparison: bool = False,
+ return_type: Optional[
+ Union[Type["TypeEngine[_T]"], "TypeEngine[_T]"]
+ ] = None,
+ natural_self_precedent: bool = False,
+ eager_grouping: bool = False,
python_impl=None,
):
self.opstring = opstring
)
self.python_impl = python_impl
- def __eq__(self, other):
+ def __eq__(self, other: Any) -> bool:
return isinstance(other, custom_op) and other.opstring == self.opstring
- def __hash__(self):
+ def __hash__(self) -> int:
return id(self)
- def __call__(self, left, right, **kw):
+ @overload
+ def __call__(
+ self, left: "ColumnElement", right: Any, **kw
+ ) -> "BinaryExpression[_T]":
+ ...
+
+ @overload
+ def __call__(
+ self, left: "Operators[_OP_RETURN]", right: Any, **kw
+ ) -> _OP_RETURN:
+ ...
+
+ def __call__(
+ self, left: "Operators[_OP_RETURN]", right: Any, **kw
+ ) -> _OP_RETURN:
if hasattr(left, "__sa_operate__"):
return left.operate(self, right, **kw)
elif self.python_impl:
)
-class ColumnOperators(Operators):
+class ColumnOperators(Operators[_OP_RETURN]):
"""Defines boolean, comparison, and other operators for
:class:`_expression.ColumnElement` expressions.
timetuple = None
"""Hack, allows datetime objects to be compared on the LHS."""
- def __lt__(self, other):
+ if typing.TYPE_CHECKING:
+
+ def operate(
+ self, op: OperatorType, *other: Any, **kwargs: Any
+ ) -> "ColumnOperators":
+ ...
+
+ def reverse_operate(
+ self, op: OperatorType, other: Any, **kwargs: Any
+ ) -> "ColumnOperators":
+ ...
+
+ def __lt__(self, other: Any) -> "ColumnOperators":
"""Implement the ``<`` operator.
In a column context, produces the clause ``a < b``.
"""
return self.operate(lt, other)
- def __le__(self, other):
+ def __le__(self, other: Any) -> "ColumnOperators":
"""Implement the ``<=`` operator.
In a column context, produces the clause ``a <= b``.
"""
return self.operate(le, other)
- __hash__ = Operators.__hash__
+ # TODO: not sure why we have this
+ __hash__ = Operators.__hash__ # type: ignore
- def __eq__(self, other):
+ def __eq__(self, other: Any) -> "ColumnOperators":
"""Implement the ``==`` operator.
In a column context, produces the clause ``a = b``.
"""
return self.operate(eq, other)
- def __ne__(self, other):
+ def __ne__(self, other: Any) -> "ColumnOperators":
"""Implement the ``!=`` operator.
In a column context, produces the clause ``a != b``.
"""
return self.operate(ne, other)
- def is_distinct_from(self, other):
+ def is_distinct_from(self, other: Any) -> "ColumnOperators":
"""Implement the ``IS DISTINCT FROM`` operator.
Renders "a IS DISTINCT FROM b" on most platforms;
"""
return self.operate(is_distinct_from, other)
- def is_not_distinct_from(self, other):
+ def is_not_distinct_from(self, other: Any) -> "ColumnOperators":
"""Implement the ``IS NOT DISTINCT FROM`` operator.
Renders "a IS NOT DISTINCT FROM b" on most platforms;
# deprecated 1.4; see #5435
isnot_distinct_from = is_not_distinct_from
- def __gt__(self, other):
+ def __gt__(self, other: Any) -> "ColumnOperators":
"""Implement the ``>`` operator.
In a column context, produces the clause ``a > b``.
"""
return self.operate(gt, other)
- def __ge__(self, other):
+ def __ge__(self, other: Any) -> "ColumnOperators":
"""Implement the ``>=`` operator.
In a column context, produces the clause ``a >= b``.
"""
return self.operate(ge, other)
- def __neg__(self):
+ def __neg__(self) -> "ColumnOperators":
"""Implement the ``-`` operator.
In a column context, produces the clause ``-a``.
"""
return self.operate(neg)
- def __contains__(self, other):
+ def __contains__(self, other: Any) -> "ColumnOperators":
return self.operate(contains, other)
- def __getitem__(self, index):
+ def __getitem__(self, index: Any) -> "ColumnOperators":
"""Implement the [] operator.
This can be used by some database-specific types
"""
return self.operate(getitem, index)
- def __lshift__(self, other):
+ def __lshift__(self, other: Any) -> "ColumnOperators":
"""implement the << operator.
Not used by SQLAlchemy core, this is provided
"""
return self.operate(lshift, other)
- def __rshift__(self, other):
+ def __rshift__(self, other: Any) -> "ColumnOperators":
"""implement the >> operator.
Not used by SQLAlchemy core, this is provided
"""
return self.operate(rshift, other)
- def concat(self, other):
+ def concat(self, other: Any) -> "ColumnOperators":
"""Implement the 'concat' operator.
In a column context, produces the clause ``a || b``,
"""
return self.operate(concat_op, other)
- def like(self, other, escape=None):
+ def like(self, other: Any, escape=None) -> "ColumnOperators":
r"""Implement the ``like`` operator.
In a column context, produces the expression::
"""
return self.operate(like_op, other, escape=escape)
- def ilike(self, other, escape=None):
+ def ilike(self, other: Any, escape=None) -> "ColumnOperators":
r"""Implement the ``ilike`` operator, e.g. case insensitive LIKE.
In a column context, produces an expression either of the form::
"""
return self.operate(ilike_op, other, escape=escape)
- def in_(self, other):
+ def in_(self, other: Any) -> "ColumnOperators":
"""Implement the ``in`` operator.
In a column context, produces the clause ``column IN <other>``.
"""
return self.operate(in_op, other)
- def not_in(self, other):
+ def not_in(self, other: Any) -> "ColumnOperators":
"""implement the ``NOT IN`` operator.
This is equivalent to using negation with
# deprecated 1.4; see #5429
notin_ = not_in
- def not_like(self, other, escape=None):
+ def not_like(self, other: Any, escape=None) -> "ColumnOperators":
"""implement the ``NOT LIKE`` operator.
This is equivalent to using negation with
# deprecated 1.4; see #5435
notlike = not_like
- def not_ilike(self, other, escape=None):
+ def not_ilike(self, other: Any, escape=None) -> "ColumnOperators":
"""implement the ``NOT ILIKE`` operator.
This is equivalent to using negation with
# deprecated 1.4; see #5435
notilike = not_ilike
- def is_(self, other):
+ def is_(self, other: Any) -> "ColumnOperators":
"""Implement the ``IS`` operator.
Normally, ``IS`` is generated automatically when comparing to a
"""
return self.operate(is_, other)
- def is_not(self, other):
+ def is_not(self, other: Any) -> "ColumnOperators":
"""Implement the ``IS NOT`` operator.
Normally, ``IS NOT`` is generated automatically when comparing to a
# deprecated 1.4; see #5429
isnot = is_not
- def startswith(self, other, **kwargs):
+ def startswith(
+ self, other: Any, escape=None, autoescape=False
+ ) -> "ColumnOperators":
r"""Implement the ``startswith`` operator.
Produces a LIKE expression that tests against a match for the start
:meth:`.ColumnOperators.like`
"""
- return self.operate(startswith_op, other, **kwargs)
+ return self.operate(
+ startswith_op, other, escape=escape, autoescape=autoescape
+ )
- def endswith(self, other, **kwargs):
+ def endswith(
+ self, other: Any, escape=None, autoescape=False
+ ) -> "ColumnOperators":
r"""Implement the 'endswith' operator.
Produces a LIKE expression that tests against a match for the end
:meth:`.ColumnOperators.like`
"""
- return self.operate(endswith_op, other, **kwargs)
+ return self.operate(
+ endswith_op, other, escape=escape, autoescape=autoescape
+ )
- def contains(self, other, **kwargs):
+ def contains(
+ self, other: Any, escape=None, autoescape=False
+ ) -> "ColumnOperators":
r"""Implement the 'contains' operator.
Produces a LIKE expression that tests against a match for the middle
"""
- return self.operate(contains_op, other, **kwargs)
+ return self.operate(
+ contains_op, other, escape=escape, autoescape=autoescape
+ )
- def match(self, other, **kwargs):
+ def match(self, other: Any, **kwargs) -> "ColumnOperators":
"""Implements a database-specific 'match' operator.
:meth:`_sql.ColumnOperators.match` attempts to resolve to
"""
return self.operate(match_op, other, **kwargs)
- def regexp_match(self, pattern, flags=None):
+ def regexp_match(self, pattern, flags=None) -> "ColumnOperators":
"""Implements a database-specific 'regexp match' operator.
E.g.::
"""
return self.operate(regexp_match_op, pattern, flags=flags)
- def regexp_replace(self, pattern, replacement, flags=None):
+ def regexp_replace(
+ self, pattern, replacement, flags=None
+ ) -> "ColumnOperators":
"""Implements a database-specific 'regexp replace' operator.
E.g.::
"""
return self.operate(
- regexp_replace_op, pattern, replacement=replacement, flags=flags
+ regexp_replace_op,
+ pattern,
+ replacement=replacement,
+ flags=flags,
)
- def desc(self):
+ def desc(self) -> "ColumnOperators":
"""Produce a :func:`_expression.desc` clause against the
parent object."""
return self.operate(desc_op)
- def asc(self):
+ def asc(self) -> "ColumnOperators":
"""Produce a :func:`_expression.asc` clause against the
parent object."""
return self.operate(asc_op)
- def nulls_first(self):
+ def nulls_first(self) -> "ColumnOperators":
"""Produce a :func:`_expression.nulls_first` clause against the
parent object.
# deprecated 1.4; see #5435
nullsfirst = nulls_first
- def nulls_last(self):
+ def nulls_last(self) -> "ColumnOperators":
"""Produce a :func:`_expression.nulls_last` clause against the
parent object.
# deprecated 1.4; see #5429
nullslast = nulls_last
- def collate(self, collation):
+ def collate(self, collation) -> "ColumnOperators":
"""Produce a :func:`_expression.collate` clause against
the parent object, given the collation string.
"""
return self.operate(collate, collation)
- def __radd__(self, other):
+ def __radd__(self, other: Any) -> "ColumnOperators":
"""Implement the ``+`` operator in reverse.
See :meth:`.ColumnOperators.__add__`.
"""
return self.reverse_operate(add, other)
- def __rsub__(self, other):
+ def __rsub__(self, other: Any) -> "ColumnOperators":
"""Implement the ``-`` operator in reverse.
See :meth:`.ColumnOperators.__sub__`.
"""
return self.reverse_operate(sub, other)
- def __rmul__(self, other):
+ def __rmul__(self, other: Any) -> "ColumnOperators":
"""Implement the ``*`` operator in reverse.
See :meth:`.ColumnOperators.__mul__`.
"""
return self.reverse_operate(mul, other)
- def __rmod__(self, other):
+ def __rmod__(self, other: Any) -> "ColumnOperators":
"""Implement the ``%`` operator in reverse.
See :meth:`.ColumnOperators.__mod__`.
"""
return self.reverse_operate(mod, other)
- def between(self, cleft, cright, symmetric=False):
+ def between(self, cleft, cright, symmetric=False) -> "ColumnOperators":
"""Produce a :func:`_expression.between` clause against
the parent object, given the lower and upper range.
"""
return self.operate(between_op, cleft, cright, symmetric=symmetric)
- def distinct(self):
+ def distinct(self) -> "ColumnOperators":
"""Produce a :func:`_expression.distinct` clause against the
parent object.
"""
return self.operate(distinct_op)
- def any_(self):
+ def any_(self) -> "ColumnOperators":
"""Produce an :func:`_expression.any_` clause against the
parent object.
"""
return self.operate(any_op)
- def all_(self):
+ def all_(self) -> "ColumnOperators":
"""Produce an :func:`_expression.all_` clause against the
parent object.
"""
return self.operate(all_op)
- def __add__(self, other):
+ def __add__(self, other: Any) -> "ColumnOperators":
"""Implement the ``+`` operator.
In a column context, produces the clause ``a + b``
"""
return self.operate(add, other)
- def __sub__(self, other):
+ def __sub__(self, other: Any) -> "ColumnOperators":
"""Implement the ``-`` operator.
In a column context, produces the clause ``a - b``.
"""
return self.operate(sub, other)
- def __mul__(self, other):
+ def __mul__(self, other: Any) -> "ColumnOperators":
"""Implement the ``*`` operator.
In a column context, produces the clause ``a * b``.
"""
return self.operate(mul, other)
- def __mod__(self, other):
+ def __mod__(self, other: Any) -> "ColumnOperators":
"""Implement the ``%`` operator.
In a column context, produces the clause ``a % b``.
"""
return self.operate(mod, other)
- def __truediv__(self, other):
+ def __truediv__(self, other: Any) -> "ColumnOperators":
"""Implement the ``/`` operator.
In a column context, produces the clause ``a / b``, and
"""
return self.operate(truediv, other)
- def __rtruediv__(self, other):
+ def __rtruediv__(self, other: Any) -> "ColumnOperators":
"""Implement the ``/`` operator in reverse.
See :meth:`.ColumnOperators.__truediv__`.
"""
return self.reverse_operate(truediv, other)
- def __floordiv__(self, other):
+ def __floordiv__(self, other: Any) -> "ColumnOperators":
"""Implement the ``//`` operator.
In a column context, produces the clause ``a / b``,
"""
return self.operate(floordiv, other)
- def __rfloordiv__(self, other):
+ def __rfloordiv__(self, other: Any) -> "ColumnOperators":
"""Implement the ``//`` operator in reverse.
See :meth:`.ColumnOperators.__floordiv__`.
_comparison = {eq, ne, lt, gt, ge, le}
+def _operator_fn(fn):
+ return cast(OperatorType, fn)
+
+
def commutative_op(fn):
_commutative.add(fn)
return fn
raise NotImplementedError()
+@_operator_fn
def is_true(a):
raise NotImplementedError()
istrue = is_true
+@_operator_fn
def is_false(a):
raise NotImplementedError()
@comparison_op
+@_operator_fn
def is_distinct_from(a, b):
return a.is_distinct_from(b)
@comparison_op
+@_operator_fn
def is_not_distinct_from(a, b):
return a.is_not_distinct_from(b)
@comparison_op
+@_operator_fn
def is_(a, b):
return a.is_(b)
@comparison_op
+@_operator_fn
def is_not(a, b):
return a.is_not(b)
isnot = is_not
+@_operator_fn
def collate(a, b):
return a.collate(b)
+@_operator_fn
def op(a, opstring, b):
return a.op(opstring)(b)
@comparison_op
+@_operator_fn
def like_op(a, b, escape=None):
return a.like(b, escape=escape)
@comparison_op
+@_operator_fn
def not_like_op(a, b, escape=None):
return a.notlike(b, escape=escape)
@comparison_op
+@_operator_fn
def ilike_op(a, b, escape=None):
return a.ilike(b, escape=escape)
@comparison_op
+@_operator_fn
def not_ilike_op(a, b, escape=None):
return a.not_ilike(b, escape=escape)
@comparison_op
+@_operator_fn
def between_op(a, b, c, symmetric=False):
return a.between(b, c, symmetric=symmetric)
@comparison_op
+@_operator_fn
def not_between_op(a, b, c, symmetric=False):
return ~a.between(b, c, symmetric=symmetric)
@comparison_op
+@_operator_fn
def in_op(a, b):
return a.in_(b)
@comparison_op
+@_operator_fn
def not_in_op(a, b):
return a.not_in(b)
notin_op = not_in_op
+@_operator_fn
def distinct_op(a):
return a.distinct()
+@_operator_fn
def any_op(a):
return a.any_()
+@_operator_fn
def all_op(a):
return a.all_()
-def _escaped_like_impl(fn, other, escape, autoescape):
+def _escaped_like_impl(fn, other: Any, escape, autoescape):
if autoescape:
if autoescape is not True:
util.warn(
@comparison_op
+@_operator_fn
def startswith_op(a, b, escape=None, autoescape=False):
return _escaped_like_impl(a.startswith, b, escape, autoescape)
@comparison_op
+@_operator_fn
def not_startswith_op(a, b, escape=None, autoescape=False):
return ~_escaped_like_impl(a.startswith, b, escape, autoescape)
@comparison_op
+@_operator_fn
def endswith_op(a, b, escape=None, autoescape=False):
return _escaped_like_impl(a.endswith, b, escape, autoescape)
@comparison_op
+@_operator_fn
def not_endswith_op(a, b, escape=None, autoescape=False):
return ~_escaped_like_impl(a.endswith, b, escape, autoescape)
@comparison_op
+@_operator_fn
def contains_op(a, b, escape=None, autoescape=False):
return _escaped_like_impl(a.contains, b, escape, autoescape)
@comparison_op
+@_operator_fn
def not_contains_op(a, b, escape=None, autoescape=False):
return ~_escaped_like_impl(a.contains, b, escape, autoescape)
@comparison_op
+@_operator_fn
def match_op(a, b, **kw):
return a.match(b, **kw)
@comparison_op
+@_operator_fn
def regexp_match_op(a, b, flags=None):
return a.regexp_match(b, flags=flags)
@comparison_op
+@_operator_fn
def not_regexp_match_op(a, b, flags=None):
return ~a.regexp_match(b, flags=flags)
+@_operator_fn
def regexp_replace_op(a, b, replacement, flags=None):
return a.regexp_replace(b, replacement=replacement, flags=flags)
@comparison_op
+@_operator_fn
def not_match_op(a, b, **kw):
return ~a.match(b, **kw)
notmatch_op = not_match_op
+@_operator_fn
def comma_op(a, b):
raise NotImplementedError()
+@_operator_fn
def filter_op(a, b):
raise NotImplementedError()
+@_operator_fn
def concat_op(a, b):
return a.concat(b)
+@_operator_fn
def desc_op(a):
return a.desc()
+@_operator_fn
def asc_op(a):
return a.asc()
+@_operator_fn
def nulls_first_op(a):
return a.nulls_first()
nullsfirst_op = nulls_first_op
+@_operator_fn
def nulls_last_op(a):
return a.nulls_last()
nullslast_op = nulls_last_op
+@_operator_fn
def json_getitem_op(a, b):
raise NotImplementedError()
+@_operator_fn
def json_path_getitem_op(a, b):
raise NotImplementedError()
__slots__ = ()
-class TruncatedLabelRole(SQLRole):
+class StringRole(SQLRole):
+ """mixin indicating a role that results in strings"""
+
+ __slots__ = ()
+
+
+class TruncatedLabelRole(StringRole, SQLRole):
__slots__ = ()
_role_name = "String SQL identifier"
"""
import collections
+import typing
+from typing import Any
+from typing import MutableMapping
+from typing import Optional
+from typing import overload
+from typing import Type
+from typing import TypeVar
+from typing import Union
from . import coercions
from . import ddl
from .. import exc
from .. import inspection
from .. import util
+from ..util.typing import Literal
+if typing.TYPE_CHECKING:
+ from .type_api import TypeEngine
+
+_T = TypeVar("_T", bound="Any")
+_ServerDefaultType = Union["FetchedValue", str, TextClause, ColumnElement]
RETAIN_SCHEMA = util.symbol("retain_schema")
return self._schema_item_copy(table)
-class Column(DialectKWArgs, SchemaItem, ColumnClause):
+class Column(DialectKWArgs, SchemaItem, ColumnClause[_T]):
"""Represents a column in a database table."""
__visit_name__ = "column"
inherit_cache = True
+ @overload
+ def __init__(
+ self: "Column[None]",
+ __name: str,
+ *args: SchemaEventTarget,
+ autoincrement: Union[bool, Literal["auto", "ignore_fk"]] = ...,
+ default: Optional[Any] = ...,
+ doc: Optional[str] = ...,
+ key: Optional[str] = ...,
+ index: Optional[bool] = ...,
+ info: MutableMapping[Any, Any] = ...,
+ nullable: bool = ...,
+ onupdate: Optional[Any] = ...,
+ primary_key: bool = ...,
+ server_default: Optional[_ServerDefaultType] = ...,
+ server_onupdate: Optional["FetchedValue"] = ...,
+ quote: Optional[bool] = ...,
+ unique: Optional[bool] = ...,
+ system: bool = ...,
+ comment: Optional[str] = ...,
+ **kwargs: Any,
+ ) -> None:
+ ...
+
+ @overload
+ def __init__(
+ self: "Column[None]",
+ *args: SchemaEventTarget,
+ autoincrement: Union[bool, Literal["auto", "ignore_fk"]] = ...,
+ default: Optional[Any] = ...,
+ doc: Optional[str] = ...,
+ key: Optional[str] = ...,
+ index: Optional[bool] = ...,
+ info: MutableMapping[Any, Any] = ...,
+ nullable: bool = ...,
+ onupdate: Optional[Any] = ...,
+ primary_key: bool = ...,
+ server_default: Optional[_ServerDefaultType] = ...,
+ server_onupdate: Optional["FetchedValue"] = ...,
+ quote: Optional[bool] = ...,
+ unique: Optional[bool] = ...,
+ system: bool = ...,
+ comment: Optional[str] = ...,
+ **kwargs: Any,
+ ) -> None:
+ ...
+
+ @overload
+ def __init__(
+ self,
+ __name: str,
+ __type: Union[Type["TypeEngine[_T]"], "TypeEngine[_T]"],
+ *args: SchemaEventTarget,
+ autoincrement: Union[bool, Literal["auto", "ignore_fk"]] = ...,
+ default: Optional[Any] = ...,
+ doc: Optional[str] = ...,
+ key: Optional[str] = ...,
+ index: Optional[bool] = ...,
+ info: MutableMapping[Any, Any] = ...,
+ nullable: bool = ...,
+ onupdate: Optional[Any] = ...,
+ primary_key: bool = ...,
+ server_default: Optional[_ServerDefaultType] = ...,
+ server_onupdate: Optional["FetchedValue"] = ...,
+ quote: Optional[bool] = ...,
+ unique: Optional[bool] = ...,
+ system: bool = ...,
+ comment: Optional[str] = ...,
+ **kwargs: Any,
+ ) -> None:
+ ...
+
+ @overload
+ def __init__(
+ self,
+ __type: Union[Type["TypeEngine[_T]"], "TypeEngine[_T]"],
+ *args: SchemaEventTarget,
+ autoincrement: Union[bool, Literal["auto", "ignore_fk"]] = ...,
+ default: Optional[Any] = ...,
+ doc: Optional[str] = ...,
+ key: Optional[str] = ...,
+ index: Optional[bool] = ...,
+ info: MutableMapping[Any, Any] = ...,
+ nullable: bool = ...,
+ onupdate: Optional[Any] = ...,
+ primary_key: bool = ...,
+ server_default: Optional[_ServerDefaultType] = ...,
+ server_onupdate: Optional["FetchedValue"] = ...,
+ quote: Optional[bool] = ...,
+ unique: Optional[bool] = ...,
+ system: bool = ...,
+ comment: Optional[str] = ...,
+ **kwargs: Any,
+ ) -> None:
+ ...
+
def __init__(self, *args, **kwargs):
r"""
Construct a new ``Column`` object.
from .base import prefix_anon_map
from .coercions import _document_text_coercion
from .elements import _anonymous_label
-from .elements import and_
from .elements import BindParameter
from .elements import BooleanClauseList
from .elements import ClauseElement
from .. import util
+and_ = BooleanClauseList.and_
+
+
class _OffsetLimitParam(BindParameter):
inherit_cache = True
method which allows for arbitrary column lists.
"""
- return Select._create(self)
+ return Select(self)
def join(self, right, onclause=None, isouter=False, full=False):
"""Return a :class:`_expression.Join` from this
self.isouter = isouter
self.full = full
- @classmethod
- def _create_outerjoin(cls, left, right, onclause=None, full=False):
- """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 cls(left, right, onclause, isouter=True, full=full)
-
- @classmethod
- def _create_join(
- cls, left, right, onclause=None, isouter=False, full=False
- ):
- """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::
-
- 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.
-
- .. versionadded:: 1.1
-
- .. seealso::
-
- :meth:`_expression.FromClause.join` - method form,
- based on a given left side.
-
- :class:`_expression.Join` - the type of object produced.
-
- """
-
- return cls(left, right, onclause, isouter, full)
-
@property
def description(self):
return "Join object on %s(%d) and %s(%d)" % (
):
"""Create a join condition between two tables or selectables.
- e.g.::
-
- join_condition(tablea, tableb)
-
- would produce an expression along the lines of::
-
- tablea.c.id==tableb.c.tablea_id
-
- The join is determined based on the foreign key relationships
- between the two selectables. If there are multiple ways
- to join, or no way to join, an error is raised.
-
- :param a_subset: An optional expression that is a sub-component
- of ``a``. An attempt will be made to join to just this sub-component
- first before looking at the full ``a`` construct, and if found
- will be successful even if there are other ways to join to ``a``.
- This allows the "right side" of a join to be passed thereby
- providing a "natural join".
+ See sqlalchemy.sql.util.join_condition() for full docs.
"""
constraints = cls._joincond_scan_left_right(
FROM table_a JOIN table_b ON table_a.id = table_b.a_id
"""
- return Select._create(self.left, self.right).select_from(self)
+ return Select(self.left, self.right).select_from(self)
@util.preload_module("sqlalchemy.sql.util")
def _anonymous_fromclause(self, name=None, flat=False):
@classmethod
def _factory(cls, selectable, name=None, flat=False):
- """Return an :class:`_expression.Alias` object.
-
- An :class:`_expression.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``.
-
- Similar functionality is available via the
- :meth:`_expression.FromClause.alias`
- method available on all :class:`_expression.FromClause` subclasses.
- In terms of
- a SELECT object as generated from the :func:`_expression.select`
- function, the :meth:`_expression.SelectBase.alias` method returns an
- :class:`_expression.Alias` or similar object which represents a named,
- parenthesized subquery.
-
- When an :class:`_expression.Alias` is created from a
- :class:`_schema.Table` object,
- this has the effect of the table being rendered
- as ``tablename AS aliasname`` in a SELECT statement.
-
- For :func:`_expression.select` objects, the effect is that of
- creating a named subquery, i.e. ``(select ...) AS aliasname``.
-
- The ``name`` parameter is optional, and provides the name
- to use in the rendered SQL. If blank, an "anonymous" 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 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.
-
- :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 coercions.expect(
roles.FromClauseRole, selectable, allow_select=True
).alias(name=name, flat=flat)
@classmethod
def _factory(cls, selectable, name=None):
- """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.
-
- .. versionadded:: 1.1
-
- .. seealso::
-
- :ref:`lateral_selects` - overview of usage.
-
- """
return coercions.expect(
roles.FromClauseRole, selectable, explicit_subquery=True
).lateral(name=name)
@classmethod
def _factory(cls, selectable, sampling, name=None, seed=None):
- """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::
-
- SELECT alias.people_id FROM
- people AS alias TABLESAMPLE bernoulli(:bernoulli_1)
- REPEATABLE (random())
-
- .. versionadded:: 1.1
-
- :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 coercions.expect(roles.FromClauseRole, selectable).tablesample(
sampling, name=name, seed=seed
)
"""No PK or default support so no autoincrement column."""
def __init__(self, name, *columns, **kw):
- """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.
-
- .. versionchanged:: 1.0.0 :func:`_expression.table` can now
- be imported from the plain ``sqlalchemy`` namespace like any
- other SQL element.
-
-
- :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.
- """
super(TableClause, self).__init__()
self.name = name
self._columns = DedupeColumnCollection()
]
def __init__(self, *columns, name=None, literal_binds=False):
- 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
-
- 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.
-
- """
-
super(Values, self).__init__()
self._column_args = columns
self.name = name
@classmethod
def _create_union(cls, *selects, **kwargs):
- 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(CompoundSelect.UNION, *selects, **kwargs)
@classmethod
def _create_union_all(cls, *selects):
- 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(CompoundSelect.UNION_ALL, *selects)
@classmethod
def _create_except(cls, *selects):
- 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(CompoundSelect.EXCEPT, *selects)
@classmethod
def _create_except_all(cls, *selects):
- 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(CompoundSelect.EXCEPT_ALL, *selects)
@classmethod
def _create_intersect(cls, *selects):
- 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(CompoundSelect.INTERSECT, *selects)
@classmethod
def _create_intersect_all(cls, *selects):
- 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(CompoundSelect.INTERSECT_ALL, *selects)
def _scalar_type(self):
]
@classmethod
- def _create(
- cls, *entities: Union[roles.ColumnsClauseRole, Type]
- ) -> "Select":
- r"""Construct a new :class:`_expression.Select`.
+ def _create_raw_select(cls, **kw) -> "Select":
+ """Create a :class:`.Select` using raw ``__new__`` with no coercions.
+ Used internally to build up :class:`.Select` constructs with
+ pre-established state.
- .. 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:`_future.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`.
+ stmt = Select.__new__(Select)
+ stmt.__dict__.update(kw)
+ return stmt
- .. seealso::
+ def __init__(self, *entities: Union[roles.ColumnsClauseRole, Type]):
+ r"""Construct a new :class:`_expression.Select`.
- :ref:`coretutorial_selecting` - Core Tutorial description of
- :func:`_expression.select`.
-
- :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 public constructor for :class:`_expression.Select` is the
+ :func:`_sql.select` function.
"""
- self = cls.__new__(cls)
self._raw_columns = [
coercions.expect(
roles.ColumnsClauseRole, ent, apply_propagate_attrs=self
GenerativeSelect.__init__(self)
- return self
-
- @classmethod
- def _create_raw_select(cls, **kw) -> "Select":
- """Create a :class:`.Select` using raw ``__new__`` with no coercions.
-
- Used internally to build up :class:`.Select` constructs with
- pre-established state.
-
- """
-
- stmt = Select.__new__(Select)
- stmt.__dict__.update(kw)
- return stmt
-
- def __init__(self):
- raise NotImplementedError()
-
def _scalar_type(self):
elem = self._raw_columns[0]
cols = list(elem._select_iterable)
"""
- _from_objects = []
+ _from_objects = ()
inherit_cache = True
- def __init__(self, *args, **kwargs):
- """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::
-
- 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
- if args and isinstance(args[0], (SelectBase, ScalarSelect)):
- s = args[0]
+ def __init__(self, __argument=None):
+ if __argument is None:
+ s = Select(literal_column("*")).scalar_subquery()
+ elif isinstance(__argument, (SelectBase, ScalarSelect)):
+ s = __argument
else:
- if not args:
- args = (literal_column("*"),)
- s = Select._create(*args, **kwargs).scalar_subquery()
+ s = Select(__argument).scalar_subquery()
UnaryExpression.__init__(
self,
""" # noqa
- return Select._create(self)
+ return Select(self)
def correlate(self, *fromclause):
"""Apply correlation to the subquery noted by this :class:`_sql.Exists`.
"""SQL specific types.
"""
-
import collections.abc as collections_abc
import datetime as dt
import decimal
+import enum
import json
import pickle
+from typing import Any
+from typing import Sequence
+from typing import Text as typing_Text
+from typing import Tuple
+from typing import TypeVar
+from typing import Union
from . import coercions
from . import elements
from ..util import OrderedDict
+_T = TypeVar("_T", bound="Any")
+
+
class _LookupExpressionAdapter:
"""Mixin expression adaptations based on lookup tables.
comparator_factory = Comparator
-class String(Concatenable, TypeEngine):
+class String(Concatenable, TypeEngine[typing_Text]):
"""The base for all string and character types.
__visit_name__ = "string"
def __init__(
- self,
+ # note pylance appears to require the "self" type in a constructor
+ # for the _T type to be correctly recognized when we send the
+ # class as the argument, e.g. `column("somecol", String)`
+ self: "String",
length=None,
collation=None,
):
super(UnicodeText, self).__init__(length=length, **kwargs)
-class Integer(_LookupExpressionAdapter, TypeEngine):
+class Integer(_LookupExpressionAdapter, TypeEngine[int]):
"""A type for ``int`` integers."""
__visit_name__ = "big_integer"
-class Numeric(_LookupExpressionAdapter, TypeEngine):
+class Numeric(
+ _LookupExpressionAdapter, TypeEngine[Union[decimal.Decimal, float]]
+):
"""A type for fixed precision numbers, such as ``NUMERIC`` or ``DECIMAL``.
_default_decimal_return_scale = 10
def __init__(
- self,
+ self: "Numeric",
precision=None,
scale=None,
decimal_return_scale=None,
scale = None
def __init__(
- self, precision=None, asdecimal=False, decimal_return_scale=None
+ self: "Float",
+ precision=None,
+ asdecimal=False,
+ decimal_return_scale=None,
):
r"""
Construct a Float.
return None
-class DateTime(_LookupExpressionAdapter, TypeEngine):
+class DateTime(_LookupExpressionAdapter, TypeEngine[dt.datetime]):
"""A type for ``datetime.datetime()`` objects.
}
-class Date(_LookupExpressionAdapter, TypeEngine):
+class Date(_LookupExpressionAdapter, TypeEngine[dt.date]):
"""A type for ``datetime.date()`` objects."""
}
-class Time(_LookupExpressionAdapter, TypeEngine):
+class Time(_LookupExpressionAdapter, TypeEngine[dt.time]):
"""A type for ``datetime.time()`` objects."""
}
-class _Binary(TypeEngine):
+class _Binary(TypeEngine[bytes]):
"""Define base behavior for binary types."""
return _we_are_the_impl(variant_mapping["_default"])
-class Enum(Emulated, String, SchemaType):
+class Enum(Emulated, String, TypeEngine[Union[str, enum.Enum]], SchemaType):
"""Generic Enum Type.
The :class:`.Enum` type provides a set of possible string values
return super(Enum, self).python_type
-class PickleType(TypeDecorator):
+class PickleType(TypeDecorator[object]):
"""Holds Python objects, which are serialized using pickle.
PickleType builds upon the Binary type to apply Python's
return x == y
-class Boolean(Emulated, TypeEngine, SchemaType):
+class Boolean(Emulated, TypeEngine[bool], SchemaType):
"""A bool datatype.
native = True
def __init__(
- self, create_constraint=False, name=None, _create_events=True
+ self: "Boolean",
+ create_constraint=False,
+ name=None,
+ _create_events=True,
):
"""Construct a Boolean.
return processors.int_to_boolean
-class _AbstractInterval(_LookupExpressionAdapter, TypeEngine):
+class _AbstractInterval(_LookupExpressionAdapter, TypeEngine[dt.timedelta]):
@util.memoized_property
def _expression_adaptations(self):
# Based on https://www.postgresql.org/docs/current/\
return process
-class JSON(Indexable, TypeEngine):
+class JSON(Indexable, TypeEngine[Any]):
"""Represent a SQL JSON type.
.. note:: :class:`_types.JSON`
return process
-class ARRAY(SchemaEventTarget, Indexable, Concatenable, TypeEngine):
+class ARRAY(
+ SchemaEventTarget, Indexable, Concatenable, TypeEngine[Sequence[Any]]
+):
"""Represent a SQL Array type.
.. note:: This type serves as the basis for all ARRAY operations.
self.item_type._set_parent_with_dispatch(parent)
-class TupleType(TypeEngine):
+class TupleType(TypeEngine[Tuple[Any]]):
"""represent the composite type of a Tuple."""
_is_tuple_type = True
"""
import typing
+from typing import Any
+from typing import Generic
+from typing import Tuple
+from typing import Type
+from typing import TypeVar
+from typing import Union
-from . import operators
from .base import SchemaEventTarget
from .cache_key import NO_CACHE
+from .operators import ColumnOperators
from .visitors import Traversible
from .. import exc
from .. import util
# these are back-assigned by sqltypes.
-BOOLEANTYPE = None
-INTEGERTYPE = None
-NULLTYPE = None
-STRINGTYPE = None
-MATCHTYPE = None
-INDEXABLE = None
-TABLEVALUE = None
-_resolve_value_to_type = None
-
+if not typing.TYPE_CHECKING:
+ BOOLEANTYPE = None
+ INTEGERTYPE = None
+ NULLTYPE = None
+ STRINGTYPE = None
+ MATCHTYPE = None
+ INDEXABLE = None
+ TABLEVALUE = None
+ _resolve_value_to_type = None
+
+if typing.TYPE_CHECKING:
+ from .elements import ColumnElement
+ from .operators import OperatorType
+ from .sqltypes import _resolve_value_to_type
+ from .sqltypes import Boolean as BOOLEANTYPE # noqa
+ from .sqltypes import Indexable as INDEXABLE # noqa
+ from .sqltypes import MatchType as MATCHTYPE # noqa
+ from .sqltypes import NULLTYPE
+
+_T = TypeVar("_T", bound=Any)
+_CT = TypeVar("_CT", bound=Any)
# replace with pep-673 when applicable
SelfTypeEngine = typing.TypeVar("SelfTypeEngine", bound="TypeEngine")
-class TypeEngine(Traversible):
+class TypeEngine(Traversible, Generic[_T]):
"""The ultimate base class for all SQL datatypes.
Common subclasses of :class:`.TypeEngine` include
_is_array = False
_is_type_decorator = False
+ _block_from_type_affinity = False
+
render_bind_cast = False
"""Render bind casts for :attr:`.BindTyping.RENDER_CASTS` mode.
"""
- class Comparator(operators.ColumnOperators):
+ class Comparator(
+ ColumnOperators["ColumnElement"],
+ Generic[_CT],
+ ):
"""Base class for custom comparison operations defined at the
type level. See :attr:`.TypeEngine.comparator_factory`.
def __clause_element__(self):
return self.expr
- def __init__(self, expr):
+ def __init__(self, expr: "ColumnElement[_CT]"):
self.expr = expr
- self.type = expr.type
+ self.type: TypeEngine[_CT] = expr.type
@util.preload_module("sqlalchemy.sql.default_comparator")
- def operate(self, op, *other, **kwargs):
+ def operate(
+ self, op: "OperatorType", *other, **kwargs
+ ) -> "ColumnElement":
default_comparator = util.preloaded.sql_default_comparator
- o = default_comparator.operator_lookup[op.__name__]
- return o[0](self.expr, op, *(other + o[1:]), **kwargs)
+ op_fn, addtl_kw = default_comparator.operator_lookup[op.__name__]
+ if kwargs:
+ addtl_kw = addtl_kw.union(kwargs)
+ return op_fn(self.expr, op, *other, **addtl_kw)
@util.preload_module("sqlalchemy.sql.default_comparator")
- def reverse_operate(self, op, other, **kwargs):
+ def reverse_operate(
+ self, op: "OperatorType", other, **kwargs
+ ) -> "ColumnElement":
default_comparator = util.preloaded.sql_default_comparator
- o = default_comparator.operator_lookup[op.__name__]
- return o[0](self.expr, op, other, reverse=True, *o[1:], **kwargs)
-
- def _adapt_expression(self, op, other_comparator):
+ op_fn, addtl_kw = default_comparator.operator_lookup[op.__name__]
+ if kwargs:
+ addtl_kw = addtl_kw.union(kwargs)
+ return op_fn(self.expr, op, other, reverse=True, **addtl_kw)
+
+ def _adapt_expression(
+ self, op: "OperatorType", other_comparator
+ ) -> Tuple["OperatorType", "TypeEngine[_CT]"]:
"""evaluate the return type of <self> <op> <othertype>,
and apply any adaptations to the given operator.
for t in self.__class__.__mro__:
if t in (TypeEngine, UserDefinedType):
return typ
- elif issubclass(t, (TypeEngine, UserDefinedType)):
+ elif issubclass(
+ t, (TypeEngine, UserDefinedType)
+ ) and not t.__dict__.get("_block_from_type_affinity", False):
typ = t
else:
return self.__class__
return cls(**kw)
-class TypeDecorator(ExternalType, SchemaEventTarget, TypeEngine):
+class TypeDecorator(ExternalType, SchemaEventTarget, TypeEngine[_T]):
"""Allows the creation of types which add additional functionality
to an existing type.
return expression.comparator
-def to_instance(typeobj, *arg, **kw):
+def to_instance(
+ typeobj: Union[Type[TypeEngine[_T]], TypeEngine[_T], None], *arg, **kw
+) -> TypeEngine[_T]:
if typeobj is None:
return NULLTYPE
from .. import util
-join_condition = util.langhelpers.public_factory(
- Join._join_condition, ".sql.util.join_condition"
-)
+def join_condition(a, b, a_subset=None, consider_as_foreign_keys=None):
+ """Create a join condition between two tables or selectables.
+
+ e.g.::
+
+ join_condition(tablea, tableb)
+
+ would produce an expression along the lines of::
+
+ tablea.c.id==tableb.c.tablea_id
+
+ The join is determined based on the foreign key relationships
+ between the two selectables. If there are multiple ways
+ to join, or no way to join, an error is raised.
+
+ :param a_subset: An optional expression that is a sub-component
+ of ``a``. An attempt will be made to join to just this sub-component
+ first before looking at the full ``a`` construct, and if found
+ will be successful even if there are other ways to join to ``a``.
+ This allows the "right side" of a join to be passed thereby
+ providing a "natural join".
+
+ """
+ return Join._join_condition(
+ a,
+ b,
+ a_subset=a_subset,
+ consider_as_foreign_keys=consider_as_foreign_keys,
+ )
def find_join_source(clauses, join_to):
"""vendored from python 3.7"""
if getattr(annotation, "__module__", None) == "typing":
- return f'"{repr(annotation).replace("typing.", "")}"'
+ return f'"{repr(annotation).replace("typing.", "").replace("~", "")}"'
if isinstance(annotation, type):
if annotation.__module__ in ("builtins", base_module):
return repr(annotation.__qualname__)
return annotation.__module__ + "." + annotation.__qualname__
elif isinstance(annotation, typing.TypeVar):
- return f'"{annotation}"'
- return repr(annotation)
+ return f'"{repr(annotation).replace("~", "")}"'
+ return f'"{repr(annotation).replace("~", "")}"'
def inspect_formatargspec(
from .. import exc
_T = TypeVar("_T")
+_F = TypeVar("_F", bound=Callable[..., Any])
+_MP = TypeVar("_MP", bound="memoized_property[Any]")
+_MA = TypeVar("_MA", bound="HasMemoized.memoized_attribute[Any]")
+_HP = TypeVar("_HP", bound="hybridproperty")
+_HM = TypeVar("_HM", bound="hybridmethod")
def md5_hex(x):
return env[fn_name]
+_PF = TypeVar("_PF")
_TE = TypeVar("_TE")
_P = compat_typing.ParamSpec("_P")
-def public_factory(
- target: typing.Callable[_P, _TE],
- location: str,
- class_location: Optional[str] = None,
-) -> typing.Callable[_P, _TE]:
- """Produce a wrapping function for the given cls or classmethod.
-
- Rationale here is so that the __init__ method of the
- class can serve as documentation for the function.
-
- """
-
- if isinstance(target, type):
- fn = target.__init__
- callable_ = target
- doc = (
- "Construct a new :class:`%s` object. \n\n"
- "This constructor is mirrored as a public API function; "
- "see :func:`sqlalchemy%s` "
- "for a full usage and argument description."
- % (
- class_location if class_location else ".%s" % target.__name__,
- location,
- )
- )
- else:
- fn = callable_ = target
- doc = (
- "This function is mirrored; see :func:`sqlalchemy%s` "
- "for a description of arguments." % location
- )
-
- location_name = location.split(".")[-1]
- spec = compat.inspect_getfullargspec(fn)
- del spec[0][0]
- metadata = format_argspec_plus(spec, grouped=False)
- metadata["name"] = location_name
- code = (
- """\
-def %(name)s%(grouped_args)s:
- return cls(%(apply_kw)s)
-"""
- % metadata
- )
- env = {
- "cls": callable_,
- "symbol": symbol,
- "__name__": callable_.__module__,
- }
- exec(code, env)
-
- decorated = env[location_name]
-
- if hasattr(fn, "_linked_to"):
- linked_to, linked_to_location = fn._linked_to
- linked_to_doc = linked_to.__doc__
- if class_location is None:
- class_location = "%s.%s" % (target.__module__, target.__name__)
-
- linked_to_doc = inject_docstring_text(
- linked_to_doc,
- ".. container:: inherited_member\n\n "
- "This documentation is inherited from :func:`sqlalchemy%s`; "
- "this constructor, :func:`sqlalchemy%s`, "
- "creates a :class:`sqlalchemy%s` object. See that class for "
- "additional details describing this subclass."
- % (linked_to_location, location, class_location),
- 1,
- )
- decorated.__doc__ = linked_to_doc
- else:
- decorated.__doc__ = fn.__doc__
-
- decorated.__module__ = "sqlalchemy" + location.rsplit(".", 1)[0]
- if decorated.__module__ not in sys.modules:
- raise ImportError(
- "public_factory location %s is not in sys.modules"
- % (decorated.__module__,)
- )
-
- if hasattr(fn, "__func__"):
- fn.__func__.__doc__ = doc
- if not hasattr(fn.__func__, "_linked_to"):
- fn.__func__._linked_to = (decorated, location)
- else:
- fn.__doc__ = doc
- if not hasattr(fn, "_linked_to"):
- fn._linked_to = (decorated, location)
-
- return decorated
-
-
class PluginLoader:
def __init__(self, group, auto_fn=None):
self.group = group
self.__dict__[key] = value
self._memoized_keys |= {key}
- class memoized_attribute:
+ class memoized_attribute(Generic[_T]):
"""A read-only @property that is only evaluated once."""
- def __init__(self, fget, doc=None):
+ fget: Callable[..., _T]
+ __doc__: Optional[str]
+ __name__: str
+
+ def __init__(self, fget: Callable[..., _T], doc: Optional[str] = None):
self.fget = fget
self.__doc__ = doc or fget.__doc__
self.__name__ = fget.__name__
+ @overload
+ def __get__(self: _MA, obj: None, cls: Any) -> _MA:
+ ...
+
+ @overload
+ def __get__(self, obj: Any, cls: Any) -> _T:
+ ...
+
def __get__(self, obj, cls):
if obj is None:
return self
return result
@classmethod
- def memoized_instancemethod(cls, fn):
+ def memoized_instancemethod(cls, fn: Any) -> Any:
"""Decorate a method memoize its return value."""
def oneshot(self, *args, **kw):
# min mypy version 0.800
strict = True
incremental = True
-plugins = sqlalchemy.ext.mypy.plugin
+#plugins = sqlalchemy.ext.mypy.plugin
[mypy-sqlalchemy.*]
ignore_errors = True
+import operator
+from typing import cast
+
from sqlalchemy import Column
+from sqlalchemy.testing import eq_
from sqlalchemy.testing import fixtures
class TestGenerics(fixtures.TestBase):
def test_traversible_is_generic(self):
+ """test #6759"""
col = Column[int]
- assert col is Column
+
+ # looked in the source for typing._GenericAlias.
+ # col.__origin__ is Column, but it's not public API.
+ # __reduce__ could change too but seems good enough for now
+ eq_(cast(object, col).__reduce__(), (operator.getitem, (Column, int)))
is_(util.duck_type_collection(instance), None)
-class PublicFactoryTest(fixtures.TestBase):
- def _fixture(self):
- class Thingy:
- def __init__(self, value):
- "make a thingy"
- self.value = value
-
- @classmethod
- def foobar(cls, x, y):
- "do the foobar"
- return Thingy(x + y)
-
- return Thingy
-
- def test_classmethod(self):
- Thingy = self._fixture()
- foob = langhelpers.public_factory(Thingy.foobar, ".sql.elements.foob")
- eq_(foob(3, 4).value, 7)
- eq_(foob(x=3, y=4).value, 7)
- eq_(foob.__doc__, "do the foobar")
- eq_(foob.__module__, "sqlalchemy.sql.elements")
- assert Thingy.foobar.__doc__.startswith("This function is mirrored;")
-
- def test_constructor(self):
- Thingy = self._fixture()
- foob = langhelpers.public_factory(Thingy, ".sql.elements.foob")
- eq_(foob(7).value, 7)
- eq_(foob(value=7).value, 7)
- eq_(foob.__doc__, "make a thingy")
- eq_(foob.__module__, "sqlalchemy.sql.elements")
- assert Thingy.__init__.__doc__.startswith(
- "Construct a new :class:`.Thingy` object."
- )
-
-
class ArgInspectionTest(fixtures.TestBase):
def test_get_cls_kwargs(self):
class A:
def go():
with testing.expect_deprecated(
- "The AliasOption is not necessary for entities to be "
+ "The AliasOption object is not necessary for entities to be "
"matched up to a query"
):
result = (