Opened 3 years ago
Closed 3 years ago
#33260 closed Bug (fixed)
Crash when using query set select_for_update(of=(...)) with exists()
Reported by: | Hannes Ljungberg | Owned by: | Hannes Ljungberg |
---|---|---|---|
Component: | Database layer (models, ORM) | Version: | dev |
Severity: | Normal | Keywords: | |
Cc: | 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 example specifying (self,)
as an argument to of
:
Person.objects.select_for_update(of=("self",)).exists()
Will crash with the following traceback:
Traceback (most recent call last): File "/tests/django/django/test/testcases.py", line 1305, in skip_wrapper return test_func(*args, **kwargs) File "/tests/django/tests/select_for_update/tests.py", line 599, in test_select_for_update_with_exists self.assertIs(Person.objects.select_for_update(of=("self",)).exists(), True) File "/tests/django/django/db/models/query.py", line 818, in exists return self.query.has_results(using=self.db) File "/tests/django/django/db/models/sql/query.py", line 546, in has_results return compiler.has_results() File "/tests/django/django/db/models/sql/compiler.py", line 1174, in has_results return bool(self.execute_sql(SINGLE)) File "/tests/django/django/db/models/sql/compiler.py", line 1191, in execute_sql sql, params = self.as_sql() File "/tests/django/django/db/models/sql/compiler.py", line 612, in as_sql of=self.get_select_for_update_of_arguments(), File "/tests/django/django/db/models/sql/compiler.py", line 1087, in get_select_for_update_of_arguments col = _get_first_selected_col_from_model(klass_info) File "/tests/django/django/db/models/sql/compiler.py", line 1053, in _get_first_selected_col_from_model concrete_model = klass_info['model']._meta.concrete_model TypeError: 'NoneType' object is not subscriptable
Selecting a related model like:
Person.objects.select_for_update(of=("born",)).exists()
Will crash with the following traceback:
Traceback (most recent call last): File "/tests/django/django/test/testcases.py", line 1305, in skip_wrapper return test_func(*args, **kwargs) File "/tests/django/tests/select_for_update/tests.py", line 599, in test_select_for_update_with_exists self.assertIs(Person.objects.select_for_update(of=("born")).exists(), True) File "/tests/django/django/db/models/query.py", line 818, in exists return self.query.has_results(using=self.db) File "/tests/django/django/db/models/sql/query.py", line 546, in has_results return compiler.has_results() File "/tests/django/django/db/models/sql/compiler.py", line 1174, in has_results return bool(self.execute_sql(SINGLE)) File "/tests/django/django/db/models/sql/compiler.py", line 1191, in execute_sql sql, params = self.as_sql() File "/tests/django/django/db/models/sql/compiler.py", line 612, in as_sql of=self.get_select_for_update_of_arguments(), File "/tests/django/django/db/models/sql/compiler.py", line 1091, in get_select_for_update_of_arguments *klass_info.get('related_klass_infos', []), AttributeError: 'NoneType' object has no attribute 'get'
With https://code.djangoproject.com/ticket/32888 in consideration we should probably just drop locking anything as no table columns are selected.
Thinking something like:
diff --git a/django/db/models/sql/compiler.py b/django/db/models/sql/compiler.py index d1009847e7..7f6251aa34 100644 --- a/django/db/models/sql/compiler.py +++ b/django/db/models/sql/compiler.py @@ -1081,6 +1081,8 @@ class SQLCompiler: invalid_names = [] for name in self.query.select_for_update_of: klass_info = self.klass_info + if not klass_info: + continue if name == 'self': col = _get_first_selected_col_from_model(klass_info) else:
Change History (4)
comment:1 by , 3 years ago
Triage Stage: | Unreviewed → Accepted |
---|
comment:3 by , 3 years ago
Triage Stage: | Accepted → Ready for checkin |
---|
Note:
See TracTickets
for help on using tickets.
Thanks for the report. We can add an early return even before the loop: