Opened 11 months ago

Closed 11 months ago

Last modified 11 months ago

#34615 closed Bug (wontfix)

queryset.order_by().first() is not consistent with other queryset behaviours

Reported by: Iuri de Silvio Owned by: nobody
Component: Database layer (models, ORM) Version: 4.2
Severity: Normal Keywords:
Cc: Triage Stage: Unreviewed
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: yes
Easy pickings: no UI/UX: no

Description

For any other operation, an empty .order_by() remove default ordering, but it orders by pk when .first() is called.

>>> User.objects.only("pk").order_by()[:1]
SELECT "auth_user"."id"
  FROM "auth_user"
LIMIT 1
>>> User.objects.only("pk").order_by().first()
SELECT "auth_user"."id"
  FROM "auth_user"
ORDER BY "auth_user"."id" ASC
LIMIT 1

I think it is an "undefined behavior" and it should build the query without ordering.

The ~almost~ undocumented implementation for this today should be:

try:
    user = User.objects.only("pk")[0]
except IndexError:
    user = None

Change History (7)

comment:1 by Iuri de Silvio, 11 months ago

Component: UncategorizedDatabase layer (models, ORM)
Type: UncategorizedBug

comment:2 by Iuri de Silvio, 11 months ago

Has patch: set

comment:3 by Iuri de Silvio, 11 months ago

Patch needs improvement: set

comment:4 by Mariusz Felisiak, 11 months ago

Resolution: wontfix
Status: assignedclosed

We added order_by("pk") only when it's not explicitly ordered, mainly, to get the consistent and deterministic behavior on all backends. It's been that way basically forever and, IMO, we shouldn't change it. You can start a discussion on DevelopersMailingList if you don't agree.

Last edited 11 months ago by Mariusz Felisiak (previous) (diff)

comment:5 by Iuri de Silvio, 11 months ago

Thanks! I disagree a bit because if I'm explicitly disabling ordering with an empty order_by, it is not the same as not defining ordering.

I'll follow up on mailing list.

comment:6 by Mariusz Felisiak, 11 months ago

See related ticket #23805.

comment:7 by David Sanders, 11 months ago

Thanks! I disagree a bit because if I'm explicitly disabling ordering with an empty order_by, it is not the same as not defining ordering.

I get your original point, but I agree with Mariusz and the original authors adding this behaviour.

To have a first/last you must have deterministic ordering and not whatever the database feels like it wants to do otherwise this will start to introduce subtle soul-destroying bugs. I've numerous tests fail intermittently (with the same db) because we forgot to add explicit ordering.

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