summaryrefslogtreecommitdiff
path: root/django
diff options
context:
space:
mode:
authorClaude Paroz <claude@2xlibre.net>2015-05-13 17:40:57 +0200
committerClaude Paroz <claude@2xlibre.net>2015-05-15 17:08:49 +0200
commit6a0d9f068f9986c8c05e689e67be7bc22c59efc6 (patch)
treeba2194311168b562dd0b5de19d78593b4d318357 /django
parent30e57038440d7785072088c10fef3ed6e71faba5 (diff)
[1.8.x] Fixed #24757 -- Recreated MySQL index when needed during combined index removal
Thanks Thomas Recouvreux for the report and Tim Graham for the tests and review. Backport of ae635cc36 from master.
Diffstat (limited to 'django')
-rw-r--r--django/db/backends/base/schema.py31
-rw-r--r--django/db/backends/mysql/schema.py18
2 files changed, 31 insertions, 18 deletions
diff --git a/django/db/backends/base/schema.py b/django/db/backends/base/schema.py
index 041519bd00..bef956cb13 100644
--- a/django/db/backends/base/schema.py
+++ b/django/db/backends/base/schema.py
@@ -317,15 +317,7 @@ class BaseDatabaseSchemaEditor(object):
news = set(tuple(fields) for fields in new_unique_together)
# Deleted uniques
for fields in olds.difference(news):
- columns = [model._meta.get_field(field).column for field in fields]
- constraint_names = self._constraint_names(model, columns, unique=True)
- if len(constraint_names) != 1:
- raise ValueError("Found wrong number (%s) of constraints for %s(%s)" % (
- len(constraint_names),
- model._meta.db_table,
- ", ".join(columns),
- ))
- self.execute(self._delete_constraint_sql(self.sql_delete_unique, model, constraint_names[0]))
+ self._delete_composed_index(model, fields, {'unique': True}, self.sql_delete_unique)
# Created uniques
for fields in news.difference(olds):
columns = [model._meta.get_field(field).column for field in fields]
@@ -341,20 +333,23 @@ class BaseDatabaseSchemaEditor(object):
news = set(tuple(fields) for fields in new_index_together)
# Deleted indexes
for fields in olds.difference(news):
- columns = [model._meta.get_field(field).column for field in fields]
- constraint_names = self._constraint_names(model, list(columns), index=True)
- if len(constraint_names) != 1:
- raise ValueError("Found wrong number (%s) of constraints for %s(%s)" % (
- len(constraint_names),
- model._meta.db_table,
- ", ".join(columns),
- ))
- self.execute(self._delete_constraint_sql(self.sql_delete_index, model, constraint_names[0]))
+ self._delete_composed_index(model, fields, {'index': True}, self.sql_delete_index)
# Created indexes
for field_names in news.difference(olds):
fields = [model._meta.get_field(field) for field in field_names]
self.execute(self._create_index_sql(model, fields, suffix="_idx"))
+ def _delete_composed_index(self, model, fields, constraint_kwargs, sql):
+ columns = [model._meta.get_field(field).column for field in fields]
+ constraint_names = self._constraint_names(model, columns, **constraint_kwargs)
+ if len(constraint_names) != 1:
+ raise ValueError("Found wrong number (%s) of constraints for %s(%s)" % (
+ len(constraint_names),
+ model._meta.db_table,
+ ", ".join(columns),
+ ))
+ self.execute(self._delete_constraint_sql(sql, model, constraint_names[0]))
+
def alter_db_table(self, model, old_db_table, new_db_table):
"""
Renames the table a model points to.
diff --git a/django/db/backends/mysql/schema.py b/django/db/backends/mysql/schema.py
index f2f3f0a4ed..7c409598ae 100644
--- a/django/db/backends/mysql/schema.py
+++ b/django/db/backends/mysql/schema.py
@@ -62,6 +62,24 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor):
field.db_index = False
return super(DatabaseSchemaEditor, self)._model_indexes_sql(model)
+ def _delete_composed_index(self, model, fields, *args):
+ """
+ MySQL can remove an implicit FK index on a field when that field is
+ covered by another index like a unique_together. "covered" here means
+ that the more complex index starts like the simpler one.
+ http://bugs.mysql.com/bug.php?id=37910 / Django ticket #24757
+ We check here before removing the [unique|index]_together if we have to
+ recreate a FK index.
+ """
+ first_field = model._meta.get_field(fields[0])
+ if first_field.get_internal_type() == 'ForeignKey':
+ constraint_names = self._constraint_names(model, fields[0], index=True)
+ if not constraint_names:
+ self.execute(
+ self._create_index_sql(model, [model._meta.get_field(fields[0])], suffix="")
+ )
+ return super(DatabaseSchemaEditor, self)._delete_composed_index(model, fields, *args)
+
def _alter_column_type_sql(self, table, old_field, new_field, new_type):
# Keep null property of old field, if it has changed, it will be handled separately
if old_field.null: