.. topic:: SQLAlchemy Mypy Plugin Status Update
- **Updated June 27, 2022**
+ **Updated December 2022**
For SQLAlchemy 2.0, the Mypy plugin continues to work at the level at which
it reached in the SQLAlchemy 1.4 release. However, SQLAlchemy 2.0,
for ORM Declarative models that removes the need for the Mypy plugin and
delivers much more consistent behavior with generally superior capabilities.
Note that this new capability is **not
- part of SQLAlchemy 1.4, it is only in SQLAlchemy 2.0, which is not released
- yet as of June 27, 2022**.
+ part of SQLAlchemy 1.4, it is only in SQLAlchemy 2.0, which is out with beta
+ releases as of December 2022**.
The SQLAlchemy Mypy plugin, while it has technically never left the "alpha"
- stage, should **now be considered as legacy, even though it is still
- necessary for full Mypy support when using SQLAlchemy 1.4**.
+ stage, should **now be considered as deprecated in SQLAlchemy 2.0, even
+ though it is still necessary for full Mypy support when using
+ SQLAlchemy 1.4**.
The Mypy plugin itself does not solve the issue of supplying correct typing
with other typing tools such as Pylance/Pyright, Pytype, Pycharm, etc, which
:ref:`whatsnew_20_orm_declarative_typing` for background on how this
migration may proceed.
- Code that is running exclusively on **not-released-yet** SQLAlchemy version
+ Code that is running exclusively on SQLAlchemy version
2.0 and has fully migrated to the new declarative constructs will enjoy full
compliance with pep-484 as well as working correctly within IDEs and other
typing tools, without the need for plugins.
.. versionadded:: 2.0
+ .. seealso::
+
+ :meth:`.Result.tuples` - v2 equivalent method.
+
"""
return self.only_return_tuples(True) # type: ignore
Eager JOIN generation within the query is disabled.
+ .. seealso::
+
+ :meth:`_sql.Select.subquery` - v2 comparable method.
+
:param name: string name to be assigned as the alias;
this is passed through to :meth:`_expression.FromClause.alias`.
If ``None``, a name will be deterministically generated
.. seealso::
- :meth:`_expression.HasCTE.cte`
+ :meth:`_sql.Select.cte` - v2 equivalent method.
"""
return (
:class:`_query.Query`, converted
to a scalar subquery with a label of the given name.
- Analogous to :meth:`sqlalchemy.sql.expression.SelectBase.label`.
+ .. seealso::
+
+ :meth:`_sql.Select.label` - v2 comparable method.
"""
.. versionchanged:: 1.4 The :meth:`_query.Query.scalar_subquery`
method replaces the :meth:`_query.Query.as_scalar` method.
+ .. seealso::
+
+ :meth:`_sql.Select.scalar_subquery` - v2 comparable method.
+
"""
return (
:meth:`_query.Query.is_single_entity`
+ :meth:`_engine.Result.tuples` - v2 comparable method.
+
"""
self.load_options += dict(_only_return_tuples=value)
return self
.. versionadded:: 1.4
+ .. seealso::
+
+ :meth:`_sql.Select.get_label_style` - v2 equivalent method.
+
"""
return self._label_style
.. versionadded:: 1.4
+
+ .. seealso::
+
+ :meth:`_sql.Select.set_label_style` - v2 equivalent method.
+
""" # noqa
if self._label_style is not style:
self = self._generate()
This returned value is a SQL expression construct, or ``None`` if no
criterion has been established.
+ .. seealso::
+
+ :attr:`_sql.Select.whereclause` - v2 equivalent property.
+
"""
return BooleanClauseList._construct_for_whereclause(
self._where_criteria
a subquery as returned by :meth:`_query.Query.subquery` is
embedded in another :func:`_expression.select` construct.
+ .. seealso::
+
+ :meth:`_sql.Select.correlate` - v2 equivalent method.
+
"""
self._auto_correlate = False
alias: Optional[Union[Alias, Subquery]] = None,
) -> Query[Any]:
"""add a mapped entity to the list of result columns
- to be returned."""
+ to be returned.
+
+ .. seealso::
+
+ :meth:`_sql.Select.add_columns` - v2 comparable method.
+ """
if alias is not None:
# TODO: deprecate
q = q.join((subq, subq.c.email < Address.email)).\
limit(1)
+ .. seealso::
+
+ :meth:`_sql.Select.with_only_columns` - v2 comparable method.
"""
if __kw:
raise _no_kw()
self, *column: _ColumnExpressionArgument[Any]
) -> Query[Any]:
"""Add one or more column expressions to the list
- of result columns to be returned."""
+ of result columns to be returned.
+
+ .. seealso::
+
+ :meth:`_sql.Select.add_columns` - v2 comparable method.
+ """
self._raw_columns = list(self._raw_columns)
.. seealso::
:meth:`_query.Query.execution_options`
+
+ :meth:`_sql.Select.get_execution_options` - v2 comparable method.
+
"""
return self._execution_options
:meth:`_query.Query.get_execution_options`
+ :meth:`_sql.Select.execution_options` - v2 equivalent method.
+
"""
self._execution_options = self._execution_options.union(kwargs)
return self
.. versionadded:: 1.4
+ .. seealso::
+
+ :meth:`_sql.Select.where` - v2 equivalent method.
+
"""
return self.filter(*criterion)
:meth:`_query.Query.filter_by` - filter on keyword expressions.
+ :meth:`_sql.Select.where` - v2 equivalent method.
+
"""
for crit in list(criterion):
crit = coercions.expect(
:meth:`_query.Query.filter` - filter on SQL expressions.
+ :meth:`_sql.Select.filter_by` - v2 comparable method.
+
"""
from_entity = self._filter_by_zero()
:ref:`tutorial_order_by_label` - in the :ref:`unified_tutorial`
+ :meth:`_sql.Select.order_by` - v2 equivalent method.
+
"""
for assertion in (self._no_statement_condition, self._no_limit_offset):
:ref:`tutorial_order_by_label` - in the :ref:`unified_tutorial`
+ :meth:`_sql.Select.group_by` - v2 equivalent method.
+
"""
for assertion in (self._no_statement_condition, self._no_limit_offset):
group_by(User.id).\
having(func.count(Address.id) > 2)
+ .. seealso::
+
+ :meth:`_sql.Select.having` - v2 equivalent method.
+
"""
for criterion in having:
:class:`_query.Query` object will not render ORDER BY within
its SELECT statement.
+ .. seealso::
+
+ :meth:`_sql.Select.union` - v2 equivalent method.
+
"""
return self._set_op(expression.union, *q)
Works the same way as :meth:`~sqlalchemy.orm.query.Query.union`. See
that method for usage examples.
+ .. seealso::
+
+ :meth:`_sql.Select.union_all` - v2 equivalent method.
+
"""
return self._set_op(expression.union_all, *q)
Works the same way as :meth:`~sqlalchemy.orm.query.Query.union`. See
that method for usage examples.
+ .. seealso::
+
+ :meth:`_sql.Select.intersect` - v2 equivalent method.
+
"""
return self._set_op(expression.intersect, *q)
Works the same way as :meth:`~sqlalchemy.orm.query.Query.union`. See
that method for usage examples.
+ .. seealso::
+
+ :meth:`_sql.Select.intersect_all` - v2 equivalent method.
+
"""
return self._set_op(expression.intersect_all, *q)
Works the same way as :meth:`~sqlalchemy.orm.query.Query.union`. See
that method for usage examples.
+ .. seealso::
+
+ :meth:`_sql.Select.except_` - v2 equivalent method.
+
"""
return self._set_op(expression.except_, *q)
Works the same way as :meth:`~sqlalchemy.orm.query.Query.union`. See
that method for usage examples.
+ .. seealso::
+
+ :meth:`_sql.Select.except_all` - v2 equivalent method.
+
"""
return self._set_op(expression.except_all, *q)
JOIN address ON user.id=address.user_id
WHERE user.name = :name_1
+ .. seealso::
+
+ :meth:`_sql.Select.join` - v2 equivalent method.
+
:param \*props: Incoming arguments for :meth:`_query.Query.join`,
the props collection in modern use should be considered to be a one
or two argument form, either as a single "target" entity or ORM
Usage is the same as the ``join()`` method.
+ .. seealso::
+
+ :meth:`_sql.Select.outerjoin` - v2 equivalent method.
+
"""
return self.join(target, onclause=onclause, isouter=True, full=full)
:meth:`.Query.select_entity_from`
+ :meth:`_sql.Select.select_from` - v2 equivalent method.
+
"""
self._set_select_from(from_obj, False)
:meth:`_query.Query.offset`
+ :meth:`_sql.Select.slice` - v2 equivalent method.
+
"""
self._limit_clause, self._offset_clause = sql_util._make_slice(
"""Apply a ``LIMIT`` to the query and return the newly resulting
``Query``.
+ .. seealso::
+
+ :meth:`_sql.Select.limit` - v2 equivalent method.
+
"""
self._limit_clause = sql_util._offset_or_limit_clause(limit)
return self
"""Apply an ``OFFSET`` to the query and return the newly resulting
``Query``.
+ .. seealso::
+
+ :meth:`_sql.Select.offset` - v2 equivalent method.
"""
self._offset_clause = sql_util._offset_or_limit_clause(offset)
return self
in SQLAlchemy 2.0. See :ref:`migration_20_query_distinct`
for a description of this use case in 2.0.
+ .. seealso::
+
+ :meth:`_sql.Select.distinct` - v2 equivalent method.
+
:param \*expr: optional column expressions. When present,
the PostgreSQL dialect will render a ``DISTINCT ON (<expressions>)``
construct.
.. seealso::
:ref:`faq_query_deduplicating`
+
+ .. seealso::
+
+ :meth:`_engine.Result.all` - v2 comparable method.
+
+ :meth:`_engine.Result.scalars` - v2 comparable method.
"""
return self._iter().all() # type: ignore
appropriate to the entity class represented by this
:class:`_query.Query`.
+ .. seealso::
+
+ :meth:`_sql.Select.from_statement` - v2 comparable method.
+
"""
statement = coercions.expect(
roles.SelectStatementRole, statement, apply_propagate_attrs=self
:meth:`_query.Query.one_or_none`
+ :meth:`_engine.Result.first` - v2 comparable method.
+
+ :meth:`_engine.Result.scalars` - v2 comparable method.
+
"""
# replicates limit(1) behavior
if self._statement is not None:
:meth:`_query.Query.one`
+ :meth:`_engine.Result.one_or_none` - v2 comparable method.
+
+ :meth:`_engine.Result.scalar_one_or_none` - v2 comparable method.
+
"""
return self._iter().one_or_none() # type: ignore
:meth:`_query.Query.one_or_none`
+ :meth:`_engine.Result.one` - v2 comparable method.
+
+ :meth:`_engine.Result.scalar_one` - v2 comparable method.
+
"""
return self._iter().one() # type: ignore
This results in an execution of the underlying query.
+ .. seealso::
+
+ :meth:`_engine.Result.scalar` - v2 comparable method.
+
"""
# TODO: not sure why we can't use result.scalar() here
try:
session.query(literal(True)).filter(q.exists()).scalar()
+ .. seealso::
+
+ :meth:`_sql.Select.exists` - v2 comparable method.
+
"""
# .add_columns() for the case that we are a query().select_from(X),
# count distinct "name" values
session.query(func.count(distinct(User.name)))
+ .. seealso::
+
+ :ref:`migration_20_query_usage`
+
"""
col = sql.func.count(sql.literal_column("*"))
return ( # type: ignore
:ref:`orm_expression_update_delete`
-
"""
update_args = update_args or {}