From 458bc9e768ede649e8e540823dd4ec0c6383744b Mon Sep 17 00:00:00 2001 From: Simon Charette Date: Wed, 4 Oct 2023 15:30:50 -0400 Subject: [PATCH] [5.0.x] Refs #33482 -- Fixed QuerySet selecting and filtering againts Exists() with empty queryset. Thanks Tobias Bengfort for the report. Backport of ea596a52d9f905596cc5335930c8f2ac4511204c from main --- django/db/models/expressions.py | 9 +++++++++ tests/expressions/tests.py | 8 ++++++++ 2 files changed, 17 insertions(+) diff --git a/django/db/models/expressions.py b/django/db/models/expressions.py index 30d44650ec..181a04493f 100644 --- a/django/db/models/expressions.py +++ b/django/db/models/expressions.py @@ -1624,6 +1624,15 @@ class Exists(Subquery): sql = "CASE WHEN {} THEN 1 ELSE 0 END".format(sql) return sql, params + def as_sql(self, compiler, *args, **kwargs): + try: + return super().as_sql(compiler, *args, **kwargs) + except EmptyResultSet: + features = compiler.connection.features + if not features.supports_boolean_expr_in_select_clause: + return "1=0", () + return compiler.compile(Value(False)) + @deconstructible(path="django.db.models.OrderBy") class OrderBy(Expression): diff --git a/tests/expressions/tests.py b/tests/expressions/tests.py index f26a6275ea..073e2e9258 100644 --- a/tests/expressions/tests.py +++ b/tests/expressions/tests.py @@ -2294,6 +2294,14 @@ class ExistsTests(TestCase): self.assertSequenceEqual(qs, [manager]) self.assertIs(qs.get().not_exists, True) + def test_filter_by_empty_exists(self): + manager = Manager.objects.create() + qs = Manager.objects.annotate(exists=Exists(Manager.objects.none())).filter( + pk=manager.pk, exists=False + ) + self.assertSequenceEqual(qs, [manager]) + self.assertIs(qs.get().exists, False) + class FieldTransformTests(TestCase): @classmethod