From c302b2ca46754ea49c5b24fdd8b6375aafb1df96 Mon Sep 17 00:00:00 2001 From: jonathan vanasco Date: Sat, 11 Jul 2026 13:16:58 -0400 Subject: [PATCH] migration note on subqueries Under 2.0, calls to `in_` and `not_in` no longer accept an explicit `.subquery()`. Passing a `.subquery()` will cause typing issues from MyPy AND will raise runtime warnings. There was no note of this in the migration guide. This may be an effect of another change that is disclosed in the migration guide. If so, I suggest nesting this text (or improved text describing this) under that section for ease in discovery and migration. Added a note to the 2.0 migration guide. This pull request is: - [x] A documentation / typographical / small typing error fix - Good to go, no issue or tests are needed - [ ] A short code fix - please include the issue number, and create an issue if none exists, which must include a complete example of the issue. one line code fixes without an issue and demonstration will not be accepted. - Please include: `Fixes: #` in the commit message - please include tests. one line code fixes without tests will not be accepted. - [ ] A new feature implementation - please include the issue number, and create an issue if none exists, which must include a complete example of how the feature would look. - Please include: `Fixes: #` in the commit message - please include tests. **Have a nice day!** Closes: #11107 Pull-request: https://github.com/sqlalchemy/sqlalchemy/pull/11107 Pull-request-sha: f8669da225bc7687208d2389c6ae3bf3c63f6aaf Change-Id: Id33779cb126a700d9adebe5f08f9d6c085589db4 --- doc/build/Makefile | 2 +- doc/build/changelog/migration_20.rst | 33 ++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/doc/build/Makefile b/doc/build/Makefile index 325da5046e..718887dd60 100644 --- a/doc/build/Makefile +++ b/doc/build/Makefile @@ -14,7 +14,7 @@ PAPEROPT_letter = -D latex_paper_size=letter ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . # the i18n builder cannot share the environment and doctrees with the others I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . -AUTOBUILDSPHINXOPTS = -T . +AUTOBUILDSPHINXOPTS = -T -j auto . .PHONY: help clean html autobuild dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest dist-html site-mako gettext diff --git a/doc/build/changelog/migration_20.rst b/doc/build/changelog/migration_20.rst index defbc0305e..1064b4690d 100644 --- a/doc/build/changelog/migration_20.rst +++ b/doc/build/changelog/migration_20.rst @@ -549,6 +549,7 @@ The guide at :ref:`whatsnew_20_toplevel` provides an overview of new features and behaviors for SQLAlchemy 2.0 which extend beyond the base set of 1.4->2.0 API changes. + 2.0 Migration - Core Connection / Transaction --------------------------------------------- @@ -2092,6 +2093,38 @@ when using an explicit :func:`_orm.aliased` object, both from a user point of view as well as how the internals of the SQLAlchemy ORM must handle it. +Filtering with ``in_()``/``not_in()`` no longer accepts explicit subqueries +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**Synopsis** + +Support for accepting explicit subqueries in specific filtering operations, such +as :meth:`_sql.ColumnOperators.in_` and +:meth:`_sql.ColumnOperators.not_in`, has been removed in 2.0. The following +legacy usage will raise warnings and is incompatible with the type checking +system:: + + subq = (session.query(User.id).filter(User.name == "foo")).subquery() + q = session.query(User).filter(User.id.in_(subq)) + +**Migration to 2.0** + +Under 2.0, SQLAlchemy will automatically interpret a fully constructed query +passed to :meth:`_sql.ColumnOperators.in_` and +:meth:`_sql.ColumnOperators.not_in` as a subquery based on the +implied context:: + + subq = select(User.id).filter(User.name == "foo") + stmt = session.execute(select(User).filter(User.id.in_(subq))) + +**Partial Migration Notes** + +A partial migration to 2.0 in which :class:`.orm.query.Query` is still utilized, +must be updated for compliance with the new API as well:: + + subq = session.query(User.id).filter(User.name == "foo") + q = session.query(User).filter(User.id.in_(subq)) + .. _joinedload_not_uniqued: ORM Rows not uniquified by default -- 2.47.3