From ede9fac75807fe5810df66280a60e7068cc97e4a Mon Sep 17 00:00:00 2001 From: Tim Graham Date: Tue, 20 Oct 2020 00:22:56 -0400 Subject: [PATCH] Fixed #32120 -- Added DatabaseFeatures.indexes_foreign_keys. --- django/db/backends/base/features.py | 3 +++ tests/introspection/tests.py | 9 +++++--- tests/schema/tests.py | 33 +++++++++++++++++++++++------ 3 files changed, 36 insertions(+), 9 deletions(-) diff --git a/django/db/backends/base/features.py b/django/db/backends/base/features.py index 477ae96c8d2..0b315aac026 100644 --- a/django/db/backends/base/features.py +++ b/django/db/backends/base/features.py @@ -172,6 +172,9 @@ class BaseDatabaseFeatures: # Can it create foreign key constraints inline when adding columns? can_create_inline_fk = True + # Does it automatically index foreign keys? + indexes_foreign_keys = True + # Does it support CHECK constraints? supports_column_check_constraints = True supports_table_check_constraints = True diff --git a/tests/introspection/tests.py b/tests/introspection/tests.py index fd7def1defb..82a661a83d2 100644 --- a/tests/introspection/tests.py +++ b/tests/introspection/tests.py @@ -206,17 +206,20 @@ class IntrospectionTests(TransactionTestCase): constraints = connection.introspection.get_constraints(cursor, Article._meta.db_table) indexes_verified = 0 expected_columns = [ - ['reporter_id'], ['headline', 'pub_date'], - ['response_to_id'], ['headline', 'response_to_id', 'pub_date', 'reporter_id'], ] + if connection.features.indexes_foreign_keys: + expected_columns += [ + ['reporter_id'], + ['response_to_id'], + ] for val in constraints.values(): if val['index'] and not (val['primary_key'] or val['unique']): self.assertIn(val['columns'], expected_columns) self.assertEqual(val['orders'], ['ASC'] * len(val['columns'])) indexes_verified += 1 - self.assertEqual(indexes_verified, 4) + self.assertEqual(indexes_verified, len(expected_columns)) def test_get_constraints(self): def assertDetails(details, cols, primary_key=False, unique=False, index=False, check=False, foreign_key=None): diff --git a/tests/schema/tests.py b/tests/schema/tests.py index e41db7a5007..a7743deba45 100644 --- a/tests/schema/tests.py +++ b/tests/schema/tests.py @@ -292,7 +292,12 @@ class SchemaTests(TransactionTestCase): with connection.schema_editor() as editor: editor.add_field(Node, new_field) editor.execute('UPDATE schema_node SET new_parent_fk_id = %s;', [parent.pk]) - self.assertIn('new_parent_fk_id', self.get_indexes(Node._meta.db_table)) + assertIndex = ( + self.assertIn + if connection.features.indexes_foreign_keys + else self.assertNotIn + ) + assertIndex('new_parent_fk_id', self.get_indexes(Node._meta.db_table)) @skipUnlessDBFeature( 'can_create_inline_fk', @@ -316,7 +321,12 @@ class SchemaTests(TransactionTestCase): Node._meta.add_field(new_field) editor.execute('UPDATE schema_node SET new_parent_fk_id = %s;', [parent.pk]) editor.add_index(Node, Index(fields=['new_parent_fk'], name='new_parent_inline_fk_idx')) - self.assertIn('new_parent_fk_id', self.get_indexes(Node._meta.db_table)) + assertIndex = ( + self.assertIn + if connection.features.indexes_foreign_keys + else self.assertNotIn + ) + assertIndex('new_parent_fk_id', self.get_indexes(Node._meta.db_table)) @skipUnlessDBFeature('supports_foreign_keys') def test_char_field_with_db_index_to_fk(self): @@ -1161,6 +1171,7 @@ class SchemaTests(TransactionTestCase): editor.create_model(Author) editor.create_model(Book) expected_fks = 1 if connection.features.supports_foreign_keys else 0 + expected_indexes = 1 if connection.features.indexes_foreign_keys else 0 # Check the index is right to begin with. counts = self.get_constraints_count( @@ -1168,7 +1179,10 @@ class SchemaTests(TransactionTestCase): Book._meta.get_field('author').column, (Author._meta.db_table, Author._meta.pk.column), ) - self.assertEqual(counts, {'fks': expected_fks, 'uniques': 0, 'indexes': 1}) + self.assertEqual( + counts, + {'fks': expected_fks, 'uniques': 0, 'indexes': expected_indexes}, + ) old_field = Book._meta.get_field('author') new_field = OneToOneField(Author, CASCADE) @@ -1189,6 +1203,7 @@ class SchemaTests(TransactionTestCase): editor.create_model(Author) editor.create_model(Book) expected_fks = 1 if connection.features.supports_foreign_keys else 0 + expected_indexes = 1 if connection.features.indexes_foreign_keys else 0 # Check the index is right to begin with. counts = self.get_constraints_count( @@ -1196,7 +1211,10 @@ class SchemaTests(TransactionTestCase): Book._meta.get_field('author').column, (Author._meta.db_table, Author._meta.pk.column), ) - self.assertEqual(counts, {'fks': expected_fks, 'uniques': 0, 'indexes': 1}) + self.assertEqual( + counts, + {'fks': expected_fks, 'uniques': 0, 'indexes': expected_indexes}, + ) old_field = Book._meta.get_field('author') # on_delete changed from CASCADE. @@ -1211,7 +1229,10 @@ class SchemaTests(TransactionTestCase): (Author._meta.db_table, Author._meta.pk.column), ) # The index remains. - self.assertEqual(counts, {'fks': expected_fks, 'uniques': 0, 'indexes': 1}) + self.assertEqual( + counts, + {'fks': expected_fks, 'uniques': 0, 'indexes': expected_indexes}, + ) def test_alter_field_o2o_to_fk(self): with connection.schema_editor() as editor: @@ -2521,7 +2542,7 @@ class SchemaTests(TransactionTestCase): with self.assertRaisesMessage(TransactionManagementError, message): editor.execute(editor.sql_create_table % {'table': 'foo', 'definition': ''}) - @skipUnlessDBFeature('supports_foreign_keys') + @skipUnlessDBFeature('supports_foreign_keys', 'indexes_foreign_keys') def test_foreign_key_index_long_names_regression(self): """ Regression test for #21497.