Opened 8 years ago
Last modified 3 years ago
#28616 assigned Bug
DISTINCT ON and update() does the wrong thing
| Reported by: | Daniel Keller | Owned by: | Anvesh Mishra |
|---|---|---|---|
| Component: | Database layer (models, ORM) | Version: | 1.11 |
| Severity: | Normal | Keywords: | |
| Cc: | Mariusz Felisiak, Anvesh Mishra | Triage Stage: | Accepted |
| Has patch: | no | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description
If I have a model like
from django.db import models
from django.utils import timezone
class Foo(models.Model):
num = models.IntegerField(default=0)
date = models.DateTimeField(default=timezone.now)
flag = models.BooleanField(default=False)
and (with Postgresql) I do
Foo.objects.order_by('num', '-date').distinct('num').only('pk')
I get a query like
SELECT DISTINCT ON ("app_foo"."num") "app_foo"."id" AS Col1 FROM "app_foo" ORDER BY "app_foo"."num" ASC, "app_foo"."date" DESC; args=()
which returns the latest Foo for each num.
BUT, if I do
Foo.objects.order_by('num', '-date').distinct('num').update(flag=True)
then it executes
UPDATE "app_foo" SET "flag" = true; args=(True)
which updates everything.
I don't necessarily think that this behaviour should be supported, but it would be nice to at least get a NotImplementedError.
Change History (6)
comment:1 by , 8 years ago
| Cc: | added |
|---|
comment:2 by , 8 years ago
| Triage Stage: | Unreviewed → Accepted |
|---|
comment:3 by , 3 years ago
| Owner: | changed from to |
|---|---|
| Status: | new → assigned |
comment:4 by , 3 years ago
comment:5 by , 3 years ago
| Cc: | added |
|---|---|
| Owner: | removed |
| Status: | assigned → new |
comment:6 by , 3 years ago
| Owner: | set to |
|---|---|
| Status: | new → assigned |
On looking into it further it seems like the problem comes because of how the QuerySet.update() works
query = self.query.chain(sql.UpdateQuery)
The Query.chain() changes the class of the current object to UpdateQuery which removes the previous query as a new object is created i.e
SELECT DISTINCT ON ("distinct_foo"."num") "distinct_foo"."id", "distinct_foo"."num", "distinct_foo"."date", "distinct_foo"."flag" FROM "distinct_foo" ORDER BY "distinct_foo"."num" ASC, "distinct_foo"."date" DESC
and then replaces it with
UPDATE "app_foo" SET "flag" = true; args=(True)
instead of combining both.
Should we add a support for this behavior or stick to
NotImplementedError?