Opened 3 years ago

Closed 2 years ago

Last modified 2 years ago

#32888 closed Cleanup/optimization (fixed)

Document that select_for_update() doesn't lock tables when their columns are not selected.

Reported by: Hannes Ljungberg Owned by: Hannes Ljungberg
Component: Documentation Version: dev
Severity: Normal Keywords:
Cc: Triage Stage: Accepted
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

The existing test "test_for_update_of_self_when_self_is_not_selected" can be extended to demonstrate this behaviour:

diff --git a/tests/select_for_update/tests.py b/tests/select_for_update/tests.py
index 705975b760..00fa102d33 100644
--- a/tests/select_for_update/tests.py
+++ b/tests/select_for_update/tests.py
@@ -240,9 +240,15 @@ class SelectForUpdateTests(TransactionTestCase):
         select_for_update(of=['self']) when the only columns selected are from
         related tables.
         """
-        with transaction.atomic():
+        with transaction.atomic(), CaptureQueriesContext(connection) as ctx:
             values = list(Person.objects.select_related('born').select_for_update(of=('self',)).values('born__name'))
         self.assertEqual(values, [{'born__name': self.city1.name}])
+        if connection.features.select_for_update_of_column:
+            expected = ['select_for_update_person"."id']
+        else:
+            expected = ['select_for_update_person']
+        expected = [connection.ops.quote_name(value) for value in expected]
+        self.assertTrue(self.has_for_update_sql(ctx.captured_queries, of=expected))

     @skipUnlessDBFeature('has_select_for_update_nowait')
     def test_nowait_raises_error_on_block(self):

Change History (8)

comment:1 by Hannes Ljungberg, 3 years ago

Tried to understand what's happening in SQLCompiler.get_select_for_update_of_arguments and it appears like it's dependant on what tables and columns have been SELECT:ed. Looks like we only need to do this because Oracle want columns instead of tables. I wonder if we could base this on the JOIN:ed tables instead and grab the column from the predicate for Oracle?

comment:2 by Mariusz Felisiak, 3 years ago

Resolution: invalid
Status: newclosed

IMO this is an expected behavior, we changed it in the PR.

comment:3 by Hannes Ljungberg, 3 years ago

Thanks, missed that PR. IMO it's a bit unexpected that the selected fields might end up affecting FOR UPDATE. What do you think about adding a small note about this in the docs?

in reply to:  3 comment:4 by Mariusz Felisiak, 3 years ago

Replying to Hannes Ljungberg:

Thanks, missed that PR. IMO it's a bit unexpected that the selected fields might end up affecting FOR UPDATE. What do you think about adding a small note about this in the docs?

Sure, feel-free to propose a clarification.

comment:5 by Jacob Walls, 2 years ago

Component: Database layer (models, ORM)Documentation
Has patch: set
Resolution: invalid
Status: closednew
Type: BugCleanup/optimization

comment:6 by Mariusz Felisiak, 2 years ago

Owner: changed from nobody to Hannes Ljungberg
Status: newassigned
Summary: Using select_for_update with self as an of-argument gets dropped when only selecting fields on related modelDocument that select_for_update() doesn't lock tables when their columns are not selected.
Triage Stage: UnreviewedAccepted

comment:7 by GitHub <noreply@…>, 2 years ago

Resolution: fixed
Status: assignedclosed

In d400b08a:

Fixed #32888 -- Doc'd that select_for_update() only locks tables with selected columns.

comment:8 by Mariusz Felisiak <felisiak.mariusz@…>, 2 years ago

In 816e8093:

[4.0.x] Fixed #32888 -- Doc'd that select_for_update() only locks tables with selected columns.

Backport of d400b08a8baa697905daadd47a6ba12336e93336 from main

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