UpdateQuery.add_update_values always computes "direct" variable as True
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)
| Triage Stage: |
Unreviewed → Accepted
|
| Owner: |
set to Ryan P Kilby
|
| Status: |
new → assigned
|
| Patch needs improvement: |
set
|
| Needs tests: |
set
|
| Patch needs improvement: |
unset
|
| Needs tests: |
unset
|
| Triage Stage: |
Accepted → Ready for checkin
|
| Resolution: |
→ fixed
|
| Status: |
assigned → closed
|
In 11c2c9a: