#33482 closed Bug (fixed)
filter on exists-subquery with empty queryset removes whole WHERE block
| Reported by: | Tobias Bengfort | Owned by: | Simon Charette |
|---|---|---|---|
| Component: | Database layer (models, ORM) | Version: | 4.0 |
| Severity: | Normal | Keywords: | orm, EmptyResultSet, Exists |
| Cc: | Triage Stage: | Ready for checkin | |
| Has patch: | yes | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description (last modified by )
>>> qs = MyModel.objects.filter(~models.Exists(MyModel.objects.none()), name='test') >>> qs <QuerySet []> >>> print(qs.query) EmptyResultSet
With django-debug-toolbar I can still see the query, but there WHERE block is missing completely.
This seems to be very similar to #33018.
Change History (14)
comment:1 by , 4 years ago
| Description: | modified (diff) |
|---|
comment:2 by , 4 years ago
| Description: | modified (diff) |
|---|
comment:3 by , 4 years ago
| Summary: | filter on exists-subquery with emoty queryset removes whole WHERE block → filter on exists-subquery with empty queryset removes whole WHERE block |
|---|
comment:4 by , 4 years ago
| Owner: | changed from to |
|---|---|
| Status: | new → assigned |
| Triage Stage: | Unreviewed → Accepted |
| Type: | Uncategorized → Bug |
comment:5 by , 4 years ago
| Has patch: | set |
|---|
comment:6 by , 4 years ago
| Triage Stage: | Accepted → Ready for checkin |
|---|
comment:9 by , 2 years ago
| Resolution: | fixed |
|---|---|
| Status: | closed → new |
I still get this error in 4.2 if I include the empty exists expression in the filter:
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)
comment:10 by , 2 years ago
The fact the problem manifests itself when the queryset is not negated was missed during the initial patch.
Tobias, can you confirm the following PR addresses the issue.
It seemed worth continuing the discussion here instead of creating a separate ticket.
comment:11 by , 2 years ago
Thanks for the quick response! It looks good. It fixed the bug in my application.
comment:13 by , 2 years ago
| Resolution: | → fixed |
|---|---|
| Status: | new → closed |
I think that this is an issue with
Exists.as_sqlwhenself.invert is True.Since
Existsencapsulate its negation logic (see__invert__) it should catchEmptyResultSetwhen raised by itssuper()call inas_sqland return an always true predicate (e.g.1=1).Does the following patch address your issue?
django/db/models/expressions.py
tests/expressions/tests.py