[2.0.x] Fixed #28944 -- Fixed crash when chaining values()/values_list() after QuerySet.select_for_update(of=()).
Backport of c21f158295
from master
This commit is contained in:
parent
830636df73
commit
4e4619a2b8
|
@ -190,7 +190,7 @@ class SQLCompiler:
|
|||
"AS alias" for the column (possibly None).
|
||||
|
||||
The klass_info structure contains the following information:
|
||||
- Which model to instantiate
|
||||
- The base model of the query.
|
||||
- Which columns for that model are present in the query (by
|
||||
position of the select clause).
|
||||
- related_klass_infos: [f, klass_info] to descent into
|
||||
|
@ -207,20 +207,21 @@ class SQLCompiler:
|
|||
select_idx += 1
|
||||
assert not (self.query.select and self.query.default_cols)
|
||||
if self.query.default_cols:
|
||||
cols = self.get_default_columns()
|
||||
else:
|
||||
# self.query.select is a special case. These columns never go to
|
||||
# any model.
|
||||
cols = self.query.select
|
||||
if cols:
|
||||
select_list = []
|
||||
for c in self.get_default_columns():
|
||||
for col in cols:
|
||||
select_list.append(select_idx)
|
||||
select.append((c, None))
|
||||
select.append((col, None))
|
||||
select_idx += 1
|
||||
klass_info = {
|
||||
'model': self.query.model,
|
||||
'select_fields': select_list,
|
||||
}
|
||||
# self.query.select is a special case. These columns never go to
|
||||
# any model.
|
||||
for col in self.query.select:
|
||||
select.append((col, None))
|
||||
select_idx += 1
|
||||
for alias, annotation in self.query.annotation_select.items():
|
||||
annotations[alias] = select_idx
|
||||
select.append((annotation, alias))
|
||||
|
|
|
@ -37,3 +37,6 @@ Bugfixes
|
|||
|
||||
* Fixed crash on SQLite when renaming a field in a model referenced by a
|
||||
``ManyToManyField`` (:ticket:`28884`).
|
||||
|
||||
* Fixed a crash when chaining ``values()`` or ``values_list()`` after
|
||||
``QuerySet.select_for_update(of=(...))`` (:ticket:`28944`).
|
||||
|
|
|
@ -120,6 +120,28 @@ class SelectForUpdateTests(TransactionTestCase):
|
|||
expected = [value.upper() for value in expected]
|
||||
self.assertTrue(self.has_for_update_sql(ctx.captured_queries, of=expected))
|
||||
|
||||
@skipUnlessDBFeature('has_select_for_update_of')
|
||||
def test_for_update_of_followed_by_values(self):
|
||||
with transaction.atomic():
|
||||
values = list(Person.objects.select_for_update(of=('self',)).values('pk'))
|
||||
self.assertEqual(values, [{'pk': self.person.pk}])
|
||||
|
||||
@skipUnlessDBFeature('has_select_for_update_of')
|
||||
def test_for_update_of_followed_by_values_list(self):
|
||||
with transaction.atomic():
|
||||
values = list(Person.objects.select_for_update(of=('self',)).values_list('pk'))
|
||||
self.assertEqual(values, [(self.person.pk,)])
|
||||
|
||||
@skipUnlessDBFeature('has_select_for_update_of')
|
||||
def test_for_update_of_self_when_self_is_not_selected(self):
|
||||
"""
|
||||
select_for_update(of=['self']) when the only columns selected are from
|
||||
related tables.
|
||||
"""
|
||||
with transaction.atomic():
|
||||
values = list(Person.objects.select_related('born').select_for_update(of=('self',)).values('born__name'))
|
||||
self.assertEqual(values, [{'born__name': self.city1.name}])
|
||||
|
||||
@skipUnlessDBFeature('has_select_for_update_nowait')
|
||||
def test_nowait_raises_error_on_block(self):
|
||||
"""
|
||||
|
|
Loading…
Reference in New Issue