Skip to content

Commit 19e5cd7

Browse files
jbohmantimgraham
authored andcommitted
Fixed #21497 -- Forced conversion to bytes for very long index names
1 parent f88e760 commit 19e5cd7

File tree

4 files changed

+32
-3
lines changed

4 files changed

+32
-3
lines changed

Diff for: AUTHORS

+1
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ answer newbie questions, and generally made Django that much better:
123123
David Blewett <[email protected]>
124124
Artem Gnilov <[email protected]>
125125
Eric Boersma <[email protected]>
126+
Joel Bohman <[email protected]>
126127
Matías Bordese
127128
Nate Bragg <[email protected]>
128129
Sean Brant

Diff for: django/db/backends/schema.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from django.db.backends.utils import truncate_name
66
from django.db.models.fields.related import ManyToManyField
77
from django.db.transaction import atomic
8+
from django.utils.encoding import force_bytes
89
from django.utils.log import getLogger
910
from django.utils.six.moves import reduce
1011
from django.utils.six import callable
@@ -703,7 +704,7 @@ def _create_index_name(self, model, column_names, suffix=""):
703704
index_name = index_name[1:]
704705
# If it's STILL too long, just hash it down
705706
if len(index_name) > self.connection.features.max_index_name_length:
706-
index_name = hashlib.md5(index_name).hexdigest()[:self.connection.features.max_index_name_length]
707+
index_name = hashlib.md5(force_bytes(index_name)).hexdigest()[:self.connection.features.max_index_name_length]
707708
# It can't start with a number on Oracle, so prepend D if we need to
708709
if index_name[0].isdigit():
709710
index_name = "D%s" % index_name[:-1]

Diff for: tests/schema/models.py

+7
Original file line numberDiff line numberDiff line change
@@ -95,3 +95,10 @@ class UniqueTest(models.Model):
9595
class Meta:
9696
app_cache = new_app_cache
9797
unique_together = ["year", "slug"]
98+
99+
100+
class BookWithLongName(models.Model):
101+
author_foreign_key_with_really_long_field_name = models.ForeignKey(Author)
102+
103+
class Meta:
104+
app_cache = new_app_cache

Diff for: tests/schema/tests.py

+22-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@
77
from django.db.models.fields import IntegerField, TextField, CharField, SlugField
88
from django.db.models.fields.related import ManyToManyField, ForeignKey
99
from django.db.transaction import atomic
10-
from .models import Author, AuthorWithM2M, Book, BookWithSlug, BookWithM2M, Tag, TagIndexed, TagM2MTest, TagUniqueRename, UniqueTest
10+
from .models import (Author, AuthorWithM2M, Book, BookWithLongName,
11+
BookWithSlug, BookWithM2M, Tag, TagIndexed, TagM2MTest, TagUniqueRename,
12+
UniqueTest)
1113

1214

1315
class SchemaTests(TransactionTestCase):
@@ -21,7 +23,10 @@ class SchemaTests(TransactionTestCase):
2123

2224
available_apps = []
2325

24-
models = [Author, AuthorWithM2M, Book, BookWithSlug, BookWithM2M, Tag, TagIndexed, TagM2MTest, TagUniqueRename, UniqueTest]
26+
models = [
27+
Author, AuthorWithM2M, Book, BookWithLongName, BookWithSlug,
28+
BookWithM2M, Tag, TagIndexed, TagM2MTest, TagUniqueRename, UniqueTest,
29+
]
2530

2631
# Utility functions
2732

@@ -659,3 +664,18 @@ class SomeError(Exception):
659664
raise SomeError
660665
except SomeError:
661666
self.assertFalse(connection.in_atomic_block)
667+
668+
def test_foreign_key_index_long_names_regression(self):
669+
"""
670+
Regression test for #21497. Only affects databases that supports
671+
foreign keys.
672+
"""
673+
# Create the table
674+
with connection.schema_editor() as editor:
675+
editor.create_model(Author)
676+
editor.create_model(BookWithLongName)
677+
# Ensure the table is there and has the right index
678+
self.assertIn(
679+
"author_foreign_key_with_really_long_field_name_id",
680+
connection.introspection.get_indexes(connection.cursor(), BookWithLongName._meta.db_table),
681+
)

0 commit comments

Comments
 (0)