summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--django/db/models/expressions.py8
-rw-r--r--django/db/models/sql/compiler.py5
-rw-r--r--docs/releases/4.1.2.txt4
-rw-r--r--tests/aggregation/tests.py11
4 files changed, 27 insertions, 1 deletions
diff --git a/django/db/models/expressions.py b/django/db/models/expressions.py
index 822968ef56..5ed7f8fae9 100644
--- a/django/db/models/expressions.py
+++ b/django/db/models/expressions.py
@@ -1481,6 +1481,14 @@ class Exists(Subquery):
clone.negated = not self.negated
return clone
+ def get_group_by_cols(self, alias=None):
+ # self.query only gets limited to a single row in the .exists() call
+ # from self.as_sql() so deferring to Query.get_group_by_cols() is
+ # inappropriate.
+ if alias is None:
+ return [self]
+ return super().get_group_by_cols(alias)
+
def as_sql(self, compiler, connection, template=None, **extra_context):
query = self.query.exists(using=connection.alias)
try:
diff --git a/django/db/models/sql/compiler.py b/django/db/models/sql/compiler.py
index 461e1ae156..ae095170f8 100644
--- a/django/db/models/sql/compiler.py
+++ b/django/db/models/sql/compiler.py
@@ -154,7 +154,10 @@ class SQLCompiler:
expressions = self.collapse_group_by(expressions, having_group_by)
for expr in expressions:
- sql, params = self.compile(expr)
+ try:
+ sql, params = self.compile(expr)
+ except EmptyResultSet:
+ continue
sql, params = expr.select_format(self, sql, params)
params_hash = make_hashable(params)
if (sql, params_hash) not in seen:
diff --git a/docs/releases/4.1.2.txt b/docs/releases/4.1.2.txt
index 4659558f3d..96c2fefcdc 100644
--- a/docs/releases/4.1.2.txt
+++ b/docs/releases/4.1.2.txt
@@ -11,3 +11,7 @@ Bugfixes
* Fixed a regression in Django 4.1 that caused a migration crash on PostgreSQL
when adding a model with ``ExclusionConstraint`` (:ticket:`33982`).
+
+* Fixed a regression in Django 4.1 that caused aggregation over a queryset that
+ contained an ``Exists`` annotation to crash due to too many selected columns
+ (:ticket:`33992`).
diff --git a/tests/aggregation/tests.py b/tests/aggregation/tests.py
index c6d73e8042..bbd4620710 100644
--- a/tests/aggregation/tests.py
+++ b/tests/aggregation/tests.py
@@ -1663,6 +1663,17 @@ class AggregateTestCase(TestCase):
).values_list("publisher_count", flat=True)
self.assertSequenceEqual(books_breakdown, [1] * 6)
+ def test_aggregation_exists_multivalued_outeref(self):
+ self.assertCountEqual(
+ Publisher.objects.annotate(
+ books_exists=Exists(
+ Book.objects.filter(publisher=OuterRef("book__publisher"))
+ ),
+ books_count=Count("book"),
+ ),
+ Publisher.objects.all(),
+ )
+
def test_filter_in_subquery_or_aggregation(self):
"""
Filtering against an aggregate requires the usage of the HAVING clause.