Opened 3 years ago

Closed 3 years ago

Last modified 12 months ago

#18743 closed Bug (wontfix)

select_for_update() silently ignored on aggregate queries

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

Description

When used on aggregate queries, the new 1.4 select_for_update() silently omits "FOR UPDATE" from the generated SQL. Instead, I would expect Django to raise a database exception, as "SELECT FOR UPDATE" on an aggregate query does not make sense. For instance, raw PostgreSQL yields an error message:

# select max(id) from mytable for update;
ERROR: SELECT FOR UPDATE/SHARE is not allowed with aggregate functions

In constrast, a Django query containing an aggregate like Max() and also using select_for_update() does not raise an exception.

Change History (2)

comment:1 Changed 3 years ago by nicolas

  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset
  • Resolution set to wontfix
  • Status changed from new to closed

As you said, select_for_update on an aggregate wouldn't make any sense. The correct behaviour here is to silently ignore it and execute the aggregate. This is similar to what happens in databases that don't support select_for_update like SQLite (https://docs.djangoproject.com/en/dev/ref/models/querysets/#select-for-update).

comment:2 Changed 12 months ago by Josh Kupershmidt <schmiddy@…>

I agree with the OP, as I was pretty surprised by Django's behavior here myself recently when attempting to use select_for_update() in combination with a Sum() aggregate. I would have liked to see an explicit error in this case. And I think this kind of confusion may be common, see e.g.

http://stackoverflow.com/questions/18455473/why-cant-i-use-select-for-update-with-aggregate-functions

I think if we can raise an Exception for unsupported operations such as in, say:

Passing nowait=True to select_for_update() using database backends that do not support nowait, such as MySQL, will cause a DatabaseError to be raised.

Then there is a good case to be made for raising an Exception here.

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