Opened 9 years ago

Closed 9 years ago

#25081 closed Bug (fixed)

QuerySet.get() ignores order_by in DISTINCT ON queries

Reported by: Peter De Wachter Owned by: Simon Charette
Component: Database layer (models, ORM) Version: dev
Severity: Normal Keywords:
Cc: Simon Charette 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

The following query, using the PostgreSQL-specific DISTINCT ON, is mistranslated:

Model.objects.order_by('key', '-last_updated').distinct('key').get(key=x)

This generated this SQL query:

SELECT DISTINCT ON ("bug_mymodel"."key")
   "bug_mymodel"."id", "bug_mymodel"."key", "bug_mymodel"."last_updated", "bug_mymodel"."text"
FROM "bug_mymodel"
WHERE "bug_mymodel"."key" = 'xyz'

The ORDER BY request is omitted from the query, but DISTINCT ON is meaningless without sort order. Note that it is correct to use get() in this case, as it is guaranteed that there is only one result.

We expected the following SQL:

SELECT DISTINCT ON ("bug_mymodel"."key")
   "bug_mymodel"."id", "bug_mymodel"."key", "bug_mymodel"."last_updated", "bug_mymodel"."text"
FROM "bug_mymodel"
WHERE "bug_mymodel"."key" = 'xyz'
ORDER BY "bug_mymodel"."key" ASC, "bug_mymodel"."last_updated" DESC

Full test case:

class MyModel(models.Model):
    key     = models.CharField(max_length=100)
    last_updated = models.DateTimeField(auto_now=True)
    text         = models.CharField(max_length=100)

def test():
    return MyModel.objects.order_by('key', '-last_updated').distinct('key').get(key='xyz')

Attachments (1)

25081.patch (1.0 KB ) - added by Peter De Wachter 9 years ago.
Patch with unit test

Download all attachments as: .zip

Change History (7)

comment:1 by Simon Charette, 9 years ago

Cc: Simon Charette added
Triage Stage: UnreviewedAccepted
Version: 1.8master

Managed to reproduce against master. The culprit seems to be an ordering clearing when limits have been set.

I'm actually running the test suite with those lines removed since I can't think of a reason this is required.

e.g. Why do ordering should be cleared in this case

Foo.objects.order_by('bar').get()

But not this one

Foo.objects.order_by('bar')[10:20].get()

comment:2 by Simon Charette, 9 years ago

It looks like latest and earliest rely on this behavior.

@pdewacht, your proposed patch makes sense. Please submit a PR with tests.

by Peter De Wachter, 9 years ago

Attachment: 25081.patch added

Patch with unit test

comment:3 by Simon Charette, 9 years ago

Owner: changed from nobody to Simon Charette
Patch needs improvement: set
Status: newassigned

WIll turn this into a PR.

comment:4 by Simon Charette, 9 years ago

Has patch: set
Patch needs improvement: unset

Created a PR.

comment:5 by Tim Graham, 9 years ago

Triage Stage: AcceptedReady for checkin

comment:6 by Simon Charette <charette.s@…>, 9 years ago

Resolution: fixed
Status: assignedclosed

In 07577a2d:

Fixed #25081 -- Prevented DISTINCT ON ordering from being cleared in get().

Thanks to pdewacht for the patch.

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