﻿id	summary	reporter	owner	description	type	status	component	version	severity	resolution	keywords	cc	stage	has_patch	needs_docs	needs_tests	needs_better_patch	easy	ui_ux
33260	Crash when using query set select_for_update(of=(...)) with exists()	Hannes Ljungberg	Hannes Ljungberg	"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:
}}}"	Bug	closed	Database layer (models, ORM)	dev	Normal	fixed			Ready for checkin	1	0	0	0	0	0
