diff --git a/django/contrib/gis/db/backends/postgis/schema.py b/django/contrib/gis/db/backends/postgis/schema.py index 0ca5362231..70def62337 100644 --- a/django/contrib/gis/db/backends/postgis/schema.py +++ b/django/contrib/gis/db/backends/postgis/schema.py @@ -32,10 +32,14 @@ class PostGISSchemaEditor(DatabaseSchemaEditor): elif field.dim > 2 and not field.geography: # Use "nd" ops which are fast on multidimensional cases field_column = "%s %s" % (field_column, self.geom_index_ops_nd) + if kwargs.get('name') is None: + index_name = '%s_%s_id' % (model._meta.db_table, field.column) + else: + index_name = kwargs['name'] return Statement( self.sql_create_index, - name=self.quote_name('%s_%s_id' % (model._meta.db_table, field.column)), + name=self.quote_name(index_name), table=self.quote_name(model._meta.db_table), using=' USING %s' % self.geom_index_type, columns=field_column, diff --git a/tests/gis_tests/geoapp/test_indexes.py b/tests/gis_tests/geoapp/test_indexes.py index ce6b998794..d4c7d13d6d 100644 --- a/tests/gis_tests/geoapp/test_indexes.py +++ b/tests/gis_tests/geoapp/test_indexes.py @@ -2,13 +2,35 @@ from unittest import skipUnless from django.db import connection from django.db.models import Index -from django.test import TestCase +from django.test import TransactionTestCase -from ..utils import postgis +from ..utils import mysql, oracle, postgis from .models import City -class SchemaIndexesTests(TestCase): +class SchemaIndexesTests(TransactionTestCase): + available_apps = [] + models = [City] + + def get_indexes(self, table): + with connection.cursor() as cursor: + constraints = connection.introspection.get_constraints(cursor, table) + return { + name: constraint['columns'] + for name, constraint in constraints.items() + if constraint['index'] + } + + def has_spatial_indexes(self, table): + if mysql: + with connection.cursor() as cursor: + return connection.introspection.supports_spatial_index(cursor, table) + elif oracle: + # Spatial indexes in Meta.indexes are not supported by the Oracle + # backend (see #31252). + return False + return True + @skipUnless(postgis, 'This is a PostGIS-specific test.') def test_using_sql(self): index = Index(fields=['point']) @@ -17,3 +39,15 @@ class SchemaIndexesTests(TestCase): '%s USING ' % editor.quote_name(City._meta.db_table), str(index.create_sql(City, editor)), ) + + def test_index_name(self): + if not self.has_spatial_indexes(City._meta.db_table): + self.skipTest('Spatial indexes in Meta.indexes are not supported.') + index_name = 'custom_point_index_name' + index = Index(fields=['point'], name=index_name) + with connection.schema_editor() as editor: + editor.add_index(City, index) + indexes = self.get_indexes(City._meta.db_table) + self.assertIn(index_name, indexes) + self.assertEqual(indexes[index_name], ['point']) + editor.remove_index(City, index)