mirror of
				https://github.com/django/django.git
				synced 2025-10-30 17:16:10 +00:00 
			
		
		
		
	[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:
		| @@ -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): | ||||
|         """ | ||||
|   | ||||
		Reference in New Issue
	
	Block a user