#36398: select_for_update(of=...) ignores "self" when using values_list() when
not
selecting a column from the model
-------------------------------------+-------------------------------------
Reporter: OutOfFocus4 | Owner: (none)
Type: Uncategorized | Status: closed
Component: Database layer | Version: 5.2
(models, ORM) |
Severity: Normal | Resolution: needsinfo
Keywords: | Triage Stage:
| Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Comment (by OutOfFocus4):
Replying to [comment:1 Sarah Boyce]:
> Thank you for the ticket
> I needed to add `available_apps = ["django.contrib.auth"]` to the test
case and both tests passed for me on SQLite. Based off the ticket
description, I think one of them should have raised a database error? Can
you clarify how to replicate the issue?
SQLite doesn't support `SELECT ... FOR UPDATE`, so the ORM skips the code
that is raising the error. If you run the code with a PostgreSQL database,
`test_proof_of_concept` will fail; the stacktrace should end with
`django.db.utils.NotSupportedError: FOR UPDATE cannot be applied to the
nullable side of an outer join`.
This error should not occur, because the
`.select_for_update(of=("self",))` on line 47 should apply the `FOR
UPDATE` to only the `auth_user` table.
If you execute `print(User.objects.values_list("groups__name",
flat=True).order_by("groups__name").select_for_update(of=("self",)).filter(pk=1).query)`
in an `atomic` block, it prints this SQL:
`SELECT "auth_group"."name" AS "groups__name" FROM "auth_user" LEFT OUTER
JOIN "auth_user_groups" ON ("auth_user"."id" =
"auth_user_groups"."user_id") LEFT OUTER JOIN "auth_group" ON
("auth_user_groups"."group_id" = "auth_group"."id") WHERE "auth_user"."id"
= 1 ORDER BY 1 ASC FOR UPDATE`
Executing `print(User.objects.values_list("groups__name",
'pk').order_by("groups__name").select_for_update(of=("self",)).filter(pk=1).query)`
in an `atomic` block prints this SQL:
`SELECT "auth_group"."name" AS "groups__name", "auth_user"."id" AS "pk"
FROM "auth_user" LEFT OUTER JOIN "auth_user_groups" ON ("auth_user"."id" =
"auth_user_groups"."user_id") LEFT OUTER JOIN "auth_group" ON
("auth_user_groups"."group_id" = "auth_group"."id") WHERE "auth_user"."id"
= 1 ORDER BY 1 ASC FOR UPDATE OF "auth_user"`
Notice how `FOR UPDATE OF "auth_user"` is only added when a column from
the `auth_user` table is `SELECT`ed.
--
Ticket URL: <https://code.djangoproject.com/ticket/36398#comment:2>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
--
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion visit
https://groups.google.com/d/msgid/django-updates/01070196f3085f36-d22138d0-dff6-45ed-8f97-b7110e97f45c-000000%40eu-central-1.amazonses.com.