mirror of https://github.com/django/django.git
Fixed #27935 -- Fixed crash with BrinIndex name > 30 characters.
This commit is contained in:
parent
93eca976c1
commit
82bb4e684f
|
@ -1,4 +1,6 @@
|
|||
from django.db import connection
|
||||
from django.db.models import Index
|
||||
from django.utils.functional import cached_property
|
||||
|
||||
__all__ = ['BrinIndex', 'GinIndex']
|
||||
|
||||
|
@ -34,6 +36,14 @@ class BrinIndex(Index):
|
|||
schema_editor.quote_value(self.pages_per_range)) + parameters['extra']
|
||||
return parameters
|
||||
|
||||
@cached_property
|
||||
def max_name_length(self):
|
||||
# Allow an index name longer than 30 characters since the suffix
|
||||
# is 4 characters (usual limit is 3). Since this index can only be
|
||||
# used on PostgreSQL, the 30 character limit for cross-database
|
||||
# compatibility isn't applicable.
|
||||
return connection.ops.max_name_length()
|
||||
|
||||
|
||||
class GinIndex(Index):
|
||||
suffix = 'gin'
|
||||
|
|
|
@ -4,12 +4,12 @@ from django.utils.encoding import force_bytes
|
|||
|
||||
__all__ = ['Index']
|
||||
|
||||
# The max length of the names of the indexes (restricted to 30 due to Oracle)
|
||||
MAX_NAME_LENGTH = 30
|
||||
|
||||
|
||||
class Index:
|
||||
suffix = 'idx'
|
||||
# The max length of the name of the index (restricted to 30 for
|
||||
# cross-database compatibility with Oracle)
|
||||
max_name_length = 30
|
||||
|
||||
def __init__(self, fields=[], name=None):
|
||||
if not isinstance(fields, list):
|
||||
|
@ -25,8 +25,8 @@ class Index:
|
|||
self.name = name or ''
|
||||
if self.name:
|
||||
errors = self.check_name()
|
||||
if len(self.name) > MAX_NAME_LENGTH:
|
||||
errors.append('Index names cannot be longer than %s characters.' % MAX_NAME_LENGTH)
|
||||
if len(self.name) > self.max_name_length:
|
||||
errors.append('Index names cannot be longer than %s characters.' % self.max_name_length)
|
||||
if errors:
|
||||
raise ValueError(errors)
|
||||
|
||||
|
@ -100,13 +100,15 @@ class Index:
|
|||
(('-%s' if order else '%s') % column_name)
|
||||
for column_name, (field_name, order) in zip(column_names, self.fields_orders)
|
||||
]
|
||||
# The length of the parts of the name is based on the default max
|
||||
# length of 30 characters.
|
||||
hash_data = [table_name] + column_names_with_order + [self.suffix]
|
||||
self.name = '%s_%s_%s' % (
|
||||
table_name[:11],
|
||||
column_names[0][:7],
|
||||
'%s_%s' % (self._hash_generator(*hash_data), self.suffix),
|
||||
)
|
||||
assert len(self.name) <= MAX_NAME_LENGTH, (
|
||||
assert len(self.name) <= self.max_name_length, (
|
||||
'Index too long for multiple database support. Is self.suffix '
|
||||
'longer than 3 characters?'
|
||||
)
|
||||
|
|
|
@ -3,7 +3,7 @@ from django.db import connection
|
|||
from django.test import skipUnlessDBFeature
|
||||
|
||||
from . import PostgreSQLTestCase
|
||||
from .models import CharFieldModel, IntegerArrayModel
|
||||
from .models import CharFieldModel, DateTimeArrayModel, IntegerArrayModel
|
||||
|
||||
|
||||
@skipUnlessDBFeature('has_brin_index_support')
|
||||
|
@ -23,6 +23,17 @@ class BrinIndexTests(PostgreSQLTestCase):
|
|||
index_with_page_range = BrinIndex(fields=['title'], pages_per_range=16)
|
||||
self.assertNotEqual(index, index_with_page_range)
|
||||
|
||||
def test_name_auto_generation(self):
|
||||
"""
|
||||
A name longer than 30 characters (since len(BrinIndex.suffix) is 4
|
||||
rather than usual limit of 3) is okay for PostgreSQL. For this test,
|
||||
the name of the field ('datetimes') must be at least 7 characters to
|
||||
generate a name longer than 30 characters.
|
||||
"""
|
||||
index = BrinIndex(fields=['datetimes'])
|
||||
index.set_name_with_model(DateTimeArrayModel)
|
||||
self.assertEqual(index.name, 'postgres_te_datetim_abf104_brin')
|
||||
|
||||
def test_deconstruction(self):
|
||||
index = BrinIndex(fields=['title'], name='test_title_brin')
|
||||
path, args, kwargs = index.deconstruct()
|
||||
|
|
Loading…
Reference in New Issue