Loading django/db/backends/base/schema.py +4 −1 Original line number Diff line number Diff line Loading @@ -884,7 +884,7 @@ class BaseDatabaseSchemaEditor(object): return [] output = [] for field in model._meta.local_fields: if field.db_index and not field.unique: if self._field_should_be_indexed(model, field): output.append(self._create_index_sql(model, [field], suffix="")) for field_names in model._meta.index_together: Loading @@ -892,6 +892,9 @@ class BaseDatabaseSchemaEditor(object): output.append(self._create_index_sql(model, fields, suffix="_idx")) return output def _field_should_be_indexed(self, model, field): return field.db_index and not field.unique def _rename_field_sql(self, table, old_field, new_field, new_type): return self.sql_rename_column % { "table": self.quote_name(table), Loading django/db/backends/mysql/schema.py +11 −8 Original line number Diff line number Diff line Loading @@ -51,17 +51,20 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor): 'column': self.quote_name(field.column), }, [effective_default]) def _model_indexes_sql(self, model): def _field_should_be_indexed(self, model, field): create_index = super(DatabaseSchemaEditor, self)._field_should_be_indexed(model, field) storage = self.connection.introspection.get_storage_engine( self.connection.cursor(), model._meta.db_table ) if storage == "InnoDB": for field in model._meta.local_fields: if field.db_index and not field.unique and field.get_internal_type() == "ForeignKey": # Temporary setting db_index to False (in memory) to disable # index creation for FKs (index automatically created by MySQL) field.db_index = False return super(DatabaseSchemaEditor, self)._model_indexes_sql(model) # No need to create an index for ForeignKey fields except if # db_constraint=False because the index from that constraint won't be # created. if (storage == "InnoDB" and create_index and field.get_internal_type() == 'ForeignKey' and field.db_constraint): return False return create_index def _delete_composed_index(self, model, fields, *args): """ Loading tests/indexes/models.py +1 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ class CurrentTranslation(models.ForeignObject): class ArticleTranslation(models.Model): article = models.ForeignKey('indexes.Article', models.CASCADE) article_no_constraint = models.ForeignKey('indexes.Article', models.CASCADE, db_constraint=False) language = models.CharField(max_length=10, unique=True) content = models.TextField() Loading tests/indexes/tests.py +5 −2 Original line number Diff line number Diff line Loading @@ -62,7 +62,7 @@ class SchemaIndexesTests(TestCase): def test_no_index_for_foreignkey(self): """ MySQL on InnoDB already creates indexes automatically for foreign keys. (#14180). (#14180). An index should be created if db_constraint=False (#26171). """ storage = connection.introspection.get_storage_engine( connection.cursor(), ArticleTranslation._meta.db_table Loading @@ -70,4 +70,7 @@ class SchemaIndexesTests(TestCase): if storage != "InnoDB": self.skip("This test only applies to the InnoDB storage engine") index_sql = connection.schema_editor()._model_indexes_sql(ArticleTranslation) self.assertEqual(index_sql, []) self.assertEqual(index_sql, [ 'CREATE INDEX `indexes_articletranslation_99fb53c2` ' 'ON `indexes_articletranslation` (`article_no_constraint_id`)' ]) Loading
django/db/backends/base/schema.py +4 −1 Original line number Diff line number Diff line Loading @@ -884,7 +884,7 @@ class BaseDatabaseSchemaEditor(object): return [] output = [] for field in model._meta.local_fields: if field.db_index and not field.unique: if self._field_should_be_indexed(model, field): output.append(self._create_index_sql(model, [field], suffix="")) for field_names in model._meta.index_together: Loading @@ -892,6 +892,9 @@ class BaseDatabaseSchemaEditor(object): output.append(self._create_index_sql(model, fields, suffix="_idx")) return output def _field_should_be_indexed(self, model, field): return field.db_index and not field.unique def _rename_field_sql(self, table, old_field, new_field, new_type): return self.sql_rename_column % { "table": self.quote_name(table), Loading
django/db/backends/mysql/schema.py +11 −8 Original line number Diff line number Diff line Loading @@ -51,17 +51,20 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor): 'column': self.quote_name(field.column), }, [effective_default]) def _model_indexes_sql(self, model): def _field_should_be_indexed(self, model, field): create_index = super(DatabaseSchemaEditor, self)._field_should_be_indexed(model, field) storage = self.connection.introspection.get_storage_engine( self.connection.cursor(), model._meta.db_table ) if storage == "InnoDB": for field in model._meta.local_fields: if field.db_index and not field.unique and field.get_internal_type() == "ForeignKey": # Temporary setting db_index to False (in memory) to disable # index creation for FKs (index automatically created by MySQL) field.db_index = False return super(DatabaseSchemaEditor, self)._model_indexes_sql(model) # No need to create an index for ForeignKey fields except if # db_constraint=False because the index from that constraint won't be # created. if (storage == "InnoDB" and create_index and field.get_internal_type() == 'ForeignKey' and field.db_constraint): return False return create_index def _delete_composed_index(self, model, fields, *args): """ Loading
tests/indexes/models.py +1 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ class CurrentTranslation(models.ForeignObject): class ArticleTranslation(models.Model): article = models.ForeignKey('indexes.Article', models.CASCADE) article_no_constraint = models.ForeignKey('indexes.Article', models.CASCADE, db_constraint=False) language = models.CharField(max_length=10, unique=True) content = models.TextField() Loading
tests/indexes/tests.py +5 −2 Original line number Diff line number Diff line Loading @@ -62,7 +62,7 @@ class SchemaIndexesTests(TestCase): def test_no_index_for_foreignkey(self): """ MySQL on InnoDB already creates indexes automatically for foreign keys. (#14180). (#14180). An index should be created if db_constraint=False (#26171). """ storage = connection.introspection.get_storage_engine( connection.cursor(), ArticleTranslation._meta.db_table Loading @@ -70,4 +70,7 @@ class SchemaIndexesTests(TestCase): if storage != "InnoDB": self.skip("This test only applies to the InnoDB storage engine") index_sql = connection.schema_editor()._model_indexes_sql(ArticleTranslation) self.assertEqual(index_sql, []) self.assertEqual(index_sql, [ 'CREATE INDEX `indexes_articletranslation_99fb53c2` ' 'ON `indexes_articletranslation` (`article_no_constraint_id`)' ])