Opened 5 years ago

Closed 5 years ago

Last modified 5 years ago

#24835 closed Bug (fixed)

exists() incorrect after annotation with Count()

Reported by: Andrew Geng Owned by: Paweł Marczewski
Component: Database layer (models, ORM) Version: 1.8
Severity: Release blocker Keywords:
Cc: josh.smeaton@… 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

exists() is returning wrong answers when I'm filtering on the results of Count(). Maybe I wanted to know whether any blog post had gotten over 100 comments. The following transcripts are on Django 1.8.1 / Python 2.7.9 / SQLite. The answer is also wrong on Python 3.4.3 but correct on Django 1.7.4.

Testcase (see below for setup)

Assume at least 2 Users exist in the database.

>>> User.objects.annotate(c=models.Count('id')).values_list('c')
[(1,), (1,)]
>>> User.objects.annotate(c=models.Count('id')).filter(c__gt=1)
[]

So far this is to be expected. No user has more than one id--which makes the following surprising.

>>> User.objects.annotate(c=models.Count('id')).filter(c__gt=1).exists()
True

What further raises the suspicion of unintended behavior is that if you increase the "1" to the number of Users (or higher), then the exists() starts to return False.

>>> User.objects.annotate(c=models.Count('id')).filter(c__gt=User.objects.count()).exists()
False

Setup

$ django-admin2 startproject blah
$ cd blah
$ ./manage.py syncdb
...
You have installed Django's auth system, and don't have any superusers defined.
Would you like to create one now? (yes/no): no
$ ./manage.py shell
>>> from django.contrib.auth.models import User
>>> User.objects.create(username='a')
>>> User.objects.create(username='b')
>>> from django.db import models

Attachments (1)

24835-test.diff (574 bytes) - added by Tim Graham 5 years ago.

Download all attachments as: .zip

Change History (9)

comment:1 Changed 5 years ago by Tim Graham

Severity: NormalRelease blocker
Triage Stage: UnreviewedAccepted

Bisected regression to 0c7633178fa9410f102e4708cef979b873bccb76. Test for Django's test suite attached.

Changed 5 years ago by Tim Graham

Attachment: 24835-test.diff added

comment:2 Changed 5 years ago by Josh Smeaton

Cc: josh.smeaton@… added

comment:3 Changed 5 years ago by Paweł Marczewski

Owner: changed from nobody to Paweł Marczewski
Status: newassigned

comment:4 Changed 5 years ago by Paweł Marczewski

Has patch: set

comment:5 Changed 5 years ago by Tim Graham

Patch needs improvement: set

comment:6 Changed 5 years ago by Josh Smeaton

Patch needs improvement: unset
Triage Stage: AcceptedReady for checkin

comment:7 Changed 5 years ago by Tim Graham <timograham@…>

Resolution: fixed
Status: assignedclosed

In 801a84ae:

Fixed #24835 -- Fixed QuerySet.exists() after an annotation with Count()

QuerySet.exists() incorrectly handled query.group_by = True
case (grouping by all select fields), causing GROUP BY
expressions to be wiped along with select fields.

comment:8 Changed 5 years ago by Tim Graham <timograham@…>

In 2aa2b9f:

[1.8.x] Fixed #24835 -- Fixed QuerySet.exists() after an annotation with Count()

QuerySet.exists() incorrectly handled query.group_by = True
case (grouping by all select fields), causing GROUP BY
expressions to be wiped along with select fields.

Backport of 801a84ae329a24d9adf01b700429fe8f1285b2b8 from master

Note: See TracTickets for help on using tickets.
Back to Top