Loading django/db/backends/mysql/introspection.py +6 −2 Original line number Diff line number Diff line Loading @@ -142,13 +142,17 @@ class DatabaseIntrospection(BaseDatabaseIntrospection): def get_storage_engine(self, cursor, table_name): """ Retrieves the storage engine for a given table. Retrieves the storage engine for a given table. Returns the default storage engine if the table doesn't exist. """ cursor.execute( "SELECT engine " "FROM information_schema.tables " "WHERE table_name = %s", [table_name]) return cursor.fetchone()[0] result = cursor.fetchone() if not result: return self.connection.features._mysql_storage_engine return result[0] def get_constraints(self, cursor, table_name): """ Loading django/db/backends/mysql/schema.py +12 −0 Original line number Diff line number Diff line Loading @@ -51,3 +51,15 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor): 'table': self.quote_name(model._meta.db_table), 'column': self.quote_name(field.column), }, [effective_default]) def _model_indexes_sql(self, model): 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) docs/releases/1.8.txt +3 −0 Original line number Diff line number Diff line Loading @@ -249,6 +249,9 @@ Database backends and up will support microseconds. See the :ref:`MySQL database notes <mysql-fractional-seconds>` for more details. * The MySQL backend no longer creates explicit indexes for foreign keys when using the InnoDB storage engine, as MySQL already creates them automatically. Email ^^^^^ Loading tests/commands_sql/tests.py +6 −6 Original line number Diff line number Diff line Loading @@ -72,14 +72,14 @@ class SQLCommandsTestCase(TestCase): with warnings.catch_warnings(): warnings.simplefilter("ignore", category=RemovedInDjango20Warning) output = sql_indexes(app_config, no_style(), connections[DEFAULT_DB_ALIAS]) # PostgreSQL creates one additional index for CharField self.assertIn(self.count_ddl(output, 'CREATE INDEX'), [3, 4]) # Number of indexes is backend-dependent self.assertTrue(1 <= self.count_ddl(output, 'CREATE INDEX') <= 4) def test_sql_destroy_indexes(self): app_config = apps.get_app_config('commands_sql') output = sql_destroy_indexes(app_config, no_style(), connections[DEFAULT_DB_ALIAS]) # PostgreSQL creates one additional index for CharField self.assertIn(self.count_ddl(output, 'DROP INDEX'), [3, 4]) # Number of indexes is backend-dependent self.assertTrue(1 <= self.count_ddl(output, 'DROP INDEX') <= 4) def test_sql_all(self): app_config = apps.get_app_config('commands_sql') Loading @@ -88,8 +88,8 @@ class SQLCommandsTestCase(TestCase): output = sql_all(app_config, no_style(), connections[DEFAULT_DB_ALIAS]) self.assertEqual(self.count_ddl(output, 'CREATE TABLE'), 3) # PostgreSQL creates one additional index for CharField self.assertIn(self.count_ddl(output, 'CREATE INDEX'), [3, 4]) # Number of indexes is backend-dependent self.assertTrue(1 <= self.count_ddl(output, 'CREATE INDEX') <= 4) class TestRouter(object): Loading tests/indexes/tests.py +15 −1 Original line number Diff line number Diff line Loading @@ -5,7 +5,7 @@ from django.db import connection from django.test import TestCase from django.test.utils import IgnorePendingDeprecationWarningsMixin from .models import Article, IndexTogetherSingleList from .models import Article, ArticleTranslation, IndexTogetherSingleList class CreationIndexesTests(IgnorePendingDeprecationWarningsMixin, TestCase): Loading Loading @@ -82,3 +82,17 @@ class SchemaIndexesTests(TestCase): """Test indexes are not created for related objects""" index_sql = connection.schema_editor()._model_indexes_sql(Article) self.assertEqual(len(index_sql), 1) @skipUnless(connection.vendor == 'mysql', "This is a mysql-specific issue") def test_no_index_for_foreignkey(self): """ MySQL on InnoDB already creates indexes automatically for foreign keys. (#14180). """ storage = connection.introspection.get_storage_engine( connection.cursor(), ArticleTranslation._meta.db_table ) 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, []) Loading
django/db/backends/mysql/introspection.py +6 −2 Original line number Diff line number Diff line Loading @@ -142,13 +142,17 @@ class DatabaseIntrospection(BaseDatabaseIntrospection): def get_storage_engine(self, cursor, table_name): """ Retrieves the storage engine for a given table. Retrieves the storage engine for a given table. Returns the default storage engine if the table doesn't exist. """ cursor.execute( "SELECT engine " "FROM information_schema.tables " "WHERE table_name = %s", [table_name]) return cursor.fetchone()[0] result = cursor.fetchone() if not result: return self.connection.features._mysql_storage_engine return result[0] def get_constraints(self, cursor, table_name): """ Loading
django/db/backends/mysql/schema.py +12 −0 Original line number Diff line number Diff line Loading @@ -51,3 +51,15 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor): 'table': self.quote_name(model._meta.db_table), 'column': self.quote_name(field.column), }, [effective_default]) def _model_indexes_sql(self, model): 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)
docs/releases/1.8.txt +3 −0 Original line number Diff line number Diff line Loading @@ -249,6 +249,9 @@ Database backends and up will support microseconds. See the :ref:`MySQL database notes <mysql-fractional-seconds>` for more details. * The MySQL backend no longer creates explicit indexes for foreign keys when using the InnoDB storage engine, as MySQL already creates them automatically. Email ^^^^^ Loading
tests/commands_sql/tests.py +6 −6 Original line number Diff line number Diff line Loading @@ -72,14 +72,14 @@ class SQLCommandsTestCase(TestCase): with warnings.catch_warnings(): warnings.simplefilter("ignore", category=RemovedInDjango20Warning) output = sql_indexes(app_config, no_style(), connections[DEFAULT_DB_ALIAS]) # PostgreSQL creates one additional index for CharField self.assertIn(self.count_ddl(output, 'CREATE INDEX'), [3, 4]) # Number of indexes is backend-dependent self.assertTrue(1 <= self.count_ddl(output, 'CREATE INDEX') <= 4) def test_sql_destroy_indexes(self): app_config = apps.get_app_config('commands_sql') output = sql_destroy_indexes(app_config, no_style(), connections[DEFAULT_DB_ALIAS]) # PostgreSQL creates one additional index for CharField self.assertIn(self.count_ddl(output, 'DROP INDEX'), [3, 4]) # Number of indexes is backend-dependent self.assertTrue(1 <= self.count_ddl(output, 'DROP INDEX') <= 4) def test_sql_all(self): app_config = apps.get_app_config('commands_sql') Loading @@ -88,8 +88,8 @@ class SQLCommandsTestCase(TestCase): output = sql_all(app_config, no_style(), connections[DEFAULT_DB_ALIAS]) self.assertEqual(self.count_ddl(output, 'CREATE TABLE'), 3) # PostgreSQL creates one additional index for CharField self.assertIn(self.count_ddl(output, 'CREATE INDEX'), [3, 4]) # Number of indexes is backend-dependent self.assertTrue(1 <= self.count_ddl(output, 'CREATE INDEX') <= 4) class TestRouter(object): Loading
tests/indexes/tests.py +15 −1 Original line number Diff line number Diff line Loading @@ -5,7 +5,7 @@ from django.db import connection from django.test import TestCase from django.test.utils import IgnorePendingDeprecationWarningsMixin from .models import Article, IndexTogetherSingleList from .models import Article, ArticleTranslation, IndexTogetherSingleList class CreationIndexesTests(IgnorePendingDeprecationWarningsMixin, TestCase): Loading Loading @@ -82,3 +82,17 @@ class SchemaIndexesTests(TestCase): """Test indexes are not created for related objects""" index_sql = connection.schema_editor()._model_indexes_sql(Article) self.assertEqual(len(index_sql), 1) @skipUnless(connection.vendor == 'mysql', "This is a mysql-specific issue") def test_no_index_for_foreignkey(self): """ MySQL on InnoDB already creates indexes automatically for foreign keys. (#14180). """ storage = connection.introspection.get_storage_engine( connection.cursor(), ArticleTranslation._meta.db_table ) 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, [])