#33482: filter on exists-subquery with empty queryset removes whole WHERE block
-------------------------------------+-------------------------------------
Reporter: Tobias Bengfort | Owner: Simon
| Charette
Type: Bug | Status: assigned
Component: Database layer | Version: 4.0
(models, ORM) |
Severity: Normal | Resolution:
Keywords: orm, | Triage Stage: Accepted
EmptyResultSet, Exists |
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Simon Charette):
* owner: nobody => Simon Charette
* status: new => assigned
* type: Uncategorized => Bug
* stage: Unreviewed => Accepted
Comment:
I think that this is an issue with `Exists.as_sql` when `self.invert is
True`.
Since `Exists` ''encapsulate'' its negation logic (see `__invert__`) it
should catch `EmptyResultSet` when raised by its `super()` call in
`as_sql` and return an always ''true'' predicate (e.g. `1=1`).
Does the following patch address your issue?
{{{#!diff
diff --git a/django/db/models/expressions.py
b/django/db/models/expressions.py
index 81f8f79c71..7ec5dad57e 100644
--- a/django/db/models/expressions.py
+++ b/django/db/models/expressions.py
@@ -1211,13 +1211,18 @@ def __invert__(self):
def as_sql(self, compiler, connection, template=None,
**extra_context):
query = self.query.exists(using=connection.alias)
- sql, params = super().as_sql(
- compiler,
- connection,
- template=template,
- query=query,
- **extra_context,
- )
+ try:
+ sql, params = super().as_sql(
+ compiler,
+ connection,
+ template=template,
+ query=query,
+ **extra_context,
+ )
+ except EmptyResultSet:
+ if self.negated:
+ return '%s = %s', (1, 1)
+ raise
if self.negated:
sql = 'NOT {}'.format(sql)
return sql, params
diff --git a/tests/expressions/tests.py b/tests/expressions/tests.py
index 5cf9dd1ea5..5d902c86e8 100644
--- a/tests/expressions/tests.py
+++ b/tests/expressions/tests.py
@@ -1905,6 +1905,13 @@ def test_optimizations(self):
)
self.assertNotIn('ORDER BY', captured_sql)
+ def test_negated_empty_exists(self):
+ manager = Manager.objects.create()
+ qs = Manager.objects.filter(
+ ~Exists(Manager.objects.none()), pk=manager.pk
+ )
+ self.assertQuerysetEqual(qs,
Manager.objects.filter(pk=manager.pk))
+
class FieldTransformTests(TestCase):
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/33482#comment:4>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
--
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/django-updates/060.85ce0bd120c958e547613192d6778c55%40djangoproject.com.