mirror of
				https://github.com/django/django.git
				synced 2025-10-31 01:25:32 +00:00 
			
		
		
		
	Fixed #18304 -- Optimized save() when update_can_self_select=False
Databases with update_can_self_select = False (MySQL for example) generated non-necessary queries when saving a multitable inherited model, and when the save resulted in update.
This commit is contained in:
		| @@ -1015,6 +1015,12 @@ class SQLUpdateCompiler(SQLCompiler): | |||||||
|         query.extra = {} |         query.extra = {} | ||||||
|         query.select = [] |         query.select = [] | ||||||
|         query.add_fields([query.model._meta.pk.name]) |         query.add_fields([query.model._meta.pk.name]) | ||||||
|  |         # Recheck the count - it is possible that fiddling with the select | ||||||
|  |         # fields above removes tables from the query. Refs #18304. | ||||||
|  |         count = query.count_active_tables() | ||||||
|  |         if not self.query.related_updates and count == 1: | ||||||
|  |             return | ||||||
|  |  | ||||||
|         must_pre_select = count > 1 and not self.connection.features.update_can_self_select |         must_pre_select = count > 1 and not self.connection.features.update_can_self_select | ||||||
|  |  | ||||||
|         # Now we adjust the current query: reset the where clause and get rid |         # Now we adjust the current query: reset the where clause and get rid | ||||||
|   | |||||||
| @@ -275,3 +275,21 @@ class ModelInheritanceTests(TestCase): | |||||||
|     def test_mixin_init(self): |     def test_mixin_init(self): | ||||||
|         m = MixinModel() |         m = MixinModel() | ||||||
|         self.assertEqual(m.other_attr, 1) |         self.assertEqual(m.other_attr, 1) | ||||||
|  |  | ||||||
|  |     def test_update_query_counts(self): | ||||||
|  |         """ | ||||||
|  |         Test that update queries do not generate non-necessary queries. | ||||||
|  |         Refs #18304. | ||||||
|  |         """ | ||||||
|  |         c = Chef.objects.create(name="Albert") | ||||||
|  |         ir = ItalianRestaurant.objects.create( | ||||||
|  |             name="Ristorante Miron", | ||||||
|  |             address="1234 W. Ash", | ||||||
|  |             serves_hot_dogs=False, | ||||||
|  |             serves_pizza=False, | ||||||
|  |             serves_gnocchi=True, | ||||||
|  |             rating=4, | ||||||
|  |             chef=c | ||||||
|  |         ) | ||||||
|  |         with self.assertNumQueries(6): | ||||||
|  |             ir.save() | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| from __future__ import absolute_import | from __future__ import absolute_import | ||||||
|  |  | ||||||
| from django.test import TestCase, skipUnlessDBFeature | from django.test import TestCase | ||||||
| from django.db.models.signals import pre_save, post_save | from django.db.models.signals import pre_save, post_save | ||||||
| from .models import Person, Employee, ProxyEmployee, Profile, Account | from .models import Person, Employee, ProxyEmployee, Profile, Account | ||||||
|  |  | ||||||
| @@ -123,9 +123,6 @@ class UpdateOnlyFieldsTests(TestCase): | |||||||
|         self.assertEqual(len(pre_save_data), 0) |         self.assertEqual(len(pre_save_data), 0) | ||||||
|         self.assertEqual(len(post_save_data), 0) |         self.assertEqual(len(post_save_data), 0) | ||||||
|  |  | ||||||
|     # A bug in SQLUpdateCompiler prevents this test from succeeding on MySQL |  | ||||||
|     # Require update_can_self_select for this test for now. Refs #18304. |  | ||||||
|     @skipUnlessDBFeature('update_can_self_select') |  | ||||||
|     def test_num_queries_inheritance(self): |     def test_num_queries_inheritance(self): | ||||||
|         s = Employee.objects.create(name='Sara', gender='F') |         s = Employee.objects.create(name='Sara', gender='F') | ||||||
|         s.employee_num = 1 |         s.employee_num = 1 | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user