Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Optimize MySQL model.save() in inheritance cases #61

Closed
wants to merge 1 commit into from

1 participant

@akaariai
Collaborator

MySQL generated non-necessary queries when saving a multitable
inherited model, and when the save resulted in update.

This issue is tracked in ticket #18304

@akaariai
Collaborator

cramm raised a good point in #django-dev - the issue is described as MySQL specific, but it is actually about "update_can_self_select". MySQL just happens to be the only core database backend with that problem. I will update the commit message.

@akaariai akaariai 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.
317e4dc
@akaariai
Collaborator

Pulled in manually in d5c7f9e

@akaariai akaariai closed this
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on May 13, 2012
  1. @akaariai

    Fixed #18304 -- Optimized save() when update_can_self_select=False

    akaariai authored
    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 page is out of date. Refresh to see the latest.
View
6 django/db/models/sql/compiler.py
@@ -1015,6 +1015,12 @@ def pre_sql_setup(self):
query.extra = {}
query.select = []
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
# Now we adjust the current query: reset the where clause and get rid
View
18 tests/modeltests/model_inheritance/tests.py
@@ -275,3 +275,21 @@ def test_multiple_table(self):
def test_mixin_init(self):
m = MixinModel()
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()
View
5 tests/modeltests/update_only_fields/tests.py
@@ -1,6 +1,6 @@
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 .models import Person, Employee, ProxyEmployee, Profile, Account
@@ -123,9 +123,6 @@ def post_save_receiver(**kwargs):
self.assertEqual(len(pre_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):
s = Employee.objects.create(name='Sara', gender='F')
s.employee_num = 1
Something went wrong with that request. Please try again.