Opened 3 months ago

Closed 3 weeks ago

#36481 closed Bug (fixed)

UpdateQuery.add_update_values always computes "direct" variable as True

Reported by: Ryan P Kilby Owned by: Ryan P Kilby
Component: Database layer (models, ORM) Version: 5.2
Severity: Normal Keywords:
Cc: Ryan P Kilby 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

For context, I've been messing around with ForeignObject in an attempt to use correlated subqueries as a join condition. e.g., defining a latest_post relation field that enables queries like Author.objects.select_related("latest_post"). Given that the relation is based on a subquery, the field is not concrete, and in testing how the queryset API works with this field, I ran into a confusing condition in QuerySet.update via the UpdateQuery.add_update_values method. In short, line 90 computes a direct variable that always resolves to true. You can verify how the boolean logic resolves with:

class UpdateTests(unittest.TestCase):

    def test_direct(self):
        testcases = [
            (True, True),
            (True, False),
            (False, True),
            (False, False),
        ]
        for auto_created, concrete in testcases:
            with self.subTest(auto_created=auto_created, concrete=concrete):
                self.assertTrue(not (auto_created and not concrete) or not concrete)

This condition should simplify to not auto_created or concrete or not concrete to concrete or not concrete to True. Digging through the blame, direct was previously provided by the model meta's .get_field_by_name(), which states "direct is True if the field exists on this model". Without fully understanding the field internals, I assume direct should have been replaced with just field.concrete. I'm not sure what the intent was for auto-created fields, but whether it's concrete seems to be the actual relevant bit, not whether it's auto-created.

Change History (8)

comment:1 by Ryan P Kilby, 3 months ago

Has patch: set

comment:2 by Sarah Boyce, 3 months ago

Triage Stage: UnreviewedAccepted

comment:3 by Sarah Boyce, 3 months ago

Owner: set to Ryan P Kilby
Status: newassigned

comment:4 by Natalia Bidart, 3 months ago

Patch needs improvement: set

comment:5 by Jacob Walls, 3 weeks ago

Needs tests: set
Patch needs improvement: unset

comment:6 by Jacob Walls, 3 weeks ago

Needs tests: unset
Triage Stage: AcceptedReady for checkin

comment:7 by Jacob Walls <jacobtylerwalls@…>, 3 weeks ago

In 11c2c9a:

Refs #36481 -- Improved test coverage for invalid updates on reverse relations.

comment:8 by Jacob Walls <jacobtylerwalls@…>, 3 weeks ago

Resolution: fixed
Status: assignedclosed

In bad03eb:

Fixed #36481 -- Fixed QuerySet.update concrete fields check.

FieldError is now emitted for invalid update calls involving reverse
relations, where previously they failed with AttributeError.

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