#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.

Reply via email to