Opened 4 years ago
Closed 4 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 , 4 years ago
| Triage Stage: | Unreviewed → Accepted |
|---|
comment:3 by , 4 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: