Opened 7 days ago

Closed 4 days ago

Last modified 4 days ago

#36301 closed Bug (fixed)

select_for_update(of) crash when used with values_list since Django 5.2 on Postgres

Reported by: Simon Charette Owned by: Simon Charette
Component: Database layer (models, ORM) Version: 5.2
Severity: Release blocker Keywords:
Cc: OutOfFocus4, Sarah Boyce 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

This was extracted from #36299 as a distinct issue.


Queryset evaluation raises an AttributeError if the database backend supports SELECT ... FOR UPDATE. The following code:

with atomic():
    values = (
        User.objects.select_for_update(of=("self",))
        .values_list(
            Concat(F("first_name"), Value(" "), F("last_name")), "email"
        )
        .get(pk=12)
    )

will fail with a stacktrace ending in AttributeError: 'Concat' object has no attribute 'target' using the Postgresql DB backend.

Replicate by Sarah as a regression in 65ad4ade74dc9208b9d686a451cd6045df0c9c3a

  • TabularUnified tests/select_for_update/tests.py

    diff --git a/tests/select_for_update/tests.py b/tests/select_for_update/tests.py
    index e8ba8f8b6e..18fca277cb 100644
    a b from django.db import (  
    1313    router,
    1414    transaction,
    1515)
     16from django.db.models import F, Value
     17from django.db.models.functions import Concat
    1618from django.test import (
    1719    TransactionTestCase,
    1820    override_settings,
    class SelectForUpdateTests(TransactionTestCase):  
    122124            list(Person.objects.select_for_update(no_key=True))
    123125        self.assertIs(self.has_for_update_sql(ctx.captured_queries, no_key=True), True)
    124126
     127    @skipUnlessDBFeature("has_select_for_update_of")
     128    def test_for_update_of_values_list(self):
     129        with transaction.atomic():
     130            values = (
     131                Person.objects.select_for_update(
     132                    of=("self",),
     133                )
     134                .values_list(Concat(Value("Dr. "), F("name")), "born")
     135            ).get(pk=self.person.pk)
     136        self.assertTupleEqual(values, ("Dr. Reinhardt", self.city1.pk))
     137
    125138    @skipUnlessDBFeature("has_select_for_update_of")

Change History (5)

comment:1 by Simon Charette, 7 days ago

Triage Stage: UnreviewedAccepted

Self-accepting since #36299 was accepted once the regression was identified.

comment:2 by Simon Charette, 7 days ago

Has patch: set

comment:3 by Mariusz Felisiak, 4 days ago

Triage Stage: AcceptedReady for checkin

comment:4 by Mariusz Felisiak <felisiak.mariusz@…>, 4 days ago

Resolution: fixed
Status: assignedclosed

In 71a19a0:

Fixed #36301 -- Fixed select_for_update(of) crash when using values()/values_list().

Regression in 65ad4ade74dc9208b9d686a451cd6045df0c9c3a which allowed for
annotations to be SELECT'ed before model field references through
values()/values_list() and broke assumptions the select_for_update(of)
table infererence logic had about model fields always being first.

Refs #28900.

Thanks OutOfFocus4 for the report and Sarah for the test.

comment:5 by Mariusz Felisiak <felisiak.mariusz@…>, 4 days ago

In 5d2a0c5:

[5.2.x] Fixed #36301 -- Fixed select_for_update(of) crash when using values()/values_list().

Regression in 65ad4ade74dc9208b9d686a451cd6045df0c9c3a which allowed for
annotations to be SELECT'ed before model field references through
values()/values_list() and broke assumptions the select_for_update(of)
table infererence logic had about model fields always being first.

Refs #28900.

Thanks OutOfFocus4 for the report and Sarah for the test.

Backport of 71a19a0e475165dbc14c1fe02f552013ee670e4c from main

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