From 1c5ec1e60999516c016e0fab60979f63060d0a0d Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Mon, 15 Mar 2021 20:01:23 -0400 Subject: [PATCH] Move enable_eagerloads(False) out of _from_self() into count() Fixed regression where calling upon :meth:`_orm.Query.count` in conjunction with a loader option such as :func:`_orm.joinedload` would fail to ignore the loader option. This is a behavior that has always been very specific to the :meth:`_orm.Query.count` method; an error is normally raised if a given :class:`_orm.Query` has options that don't apply to what it is returning. Specifically, the call to enable_eagerloads(False) inside of _from_self() is not needed as loader options are now not invoked for subqueries. Instead, set enable_eagerloads(False) in the count() method itself, so that these options won't be considered in this specific case. Fixes: #6052 Change-Id: I0059ed3fb06156ef4116fd015cbef6f89808e8ef --- lib/sqlalchemy/orm/query.py | 3 +-- test/orm/test_query.py | 13 +++++++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/lib/sqlalchemy/orm/query.py b/lib/sqlalchemy/orm/query.py index d685ac83ed..4e2b4cdebb 100644 --- a/lib/sqlalchemy/orm/query.py +++ b/lib/sqlalchemy/orm/query.py @@ -1296,7 +1296,6 @@ class Query( def _from_self(self, *entities): fromclause = ( self.set_label_style(LABEL_STYLE_TABLENAME_PLUS_COL) - .enable_eagerloads(False) .correlate(None) .subquery() ._anonymous_fromclause() @@ -3006,7 +3005,7 @@ class Query( """ col = sql.func.count(sql.literal_column("*")) - return self._from_self(col).scalar() + return self._from_self(col).enable_eagerloads(False).scalar() def delete(self, synchronize_session="evaluate"): r"""Perform a DELETE with an arbitrary WHERE clause. diff --git a/test/orm/test_query.py b/test/orm/test_query.py index c36946b6ed..05ab160074 100644 --- a/test/orm/test_query.py +++ b/test/orm/test_query.py @@ -3976,6 +3976,19 @@ class CountTest(QueryTest): 2, ) + def test_loader_options_ignored(self): + """test the count()-specific legacy behavior that loader + options are effectively ignored, as they previously were applied + before the count() function would be. + + """ + + User = self.classes.User + + s = fixture_session() + + eq_(s.query(User).options(joinedload(User.addresses)).count(), 4) + def test_count_char(self): User = self.classes.User s = fixture_session() -- 2.47.2