Fixed #21497 -- Forced conversion to bytes for very long index names

This commit is contained in:
Joel Bohman 2013-11-22 23:31:50 +01:00 committed by Tim Graham
parent f88e760869
commit 19e5cd77f0
4 changed files with 32 additions and 3 deletions

View File

@ -123,6 +123,7 @@ answer newbie questions, and generally made Django that much better:
David Blewett <david@dawninglight.net>
Artem Gnilov <boobsd@gmail.com>
Eric Boersma <eric.boersma@gmail.com>
Joel Bohman <mail@jbohman.com>
Matías Bordese
Nate Bragg <jonathan.bragg@alum.rpi.edu>
Sean Brant

View File

@ -5,6 +5,7 @@ from django.db.backends.creation import BaseDatabaseCreation
from django.db.backends.utils import truncate_name
from django.db.models.fields.related import ManyToManyField
from django.db.transaction import atomic
from django.utils.encoding import force_bytes
from django.utils.log import getLogger
from django.utils.six.moves import reduce
from django.utils.six import callable
@ -703,7 +704,7 @@ class BaseDatabaseSchemaEditor(object):
index_name = index_name[1:]
# If it's STILL too long, just hash it down
if len(index_name) > self.connection.features.max_index_name_length:
index_name = hashlib.md5(index_name).hexdigest()[:self.connection.features.max_index_name_length]
index_name = hashlib.md5(force_bytes(index_name)).hexdigest()[:self.connection.features.max_index_name_length]
# It can't start with a number on Oracle, so prepend D if we need to
if index_name[0].isdigit():
index_name = "D%s" % index_name[:-1]

View File

@ -95,3 +95,10 @@ class UniqueTest(models.Model):
class Meta:
app_cache = new_app_cache
unique_together = ["year", "slug"]
class BookWithLongName(models.Model):
author_foreign_key_with_really_long_field_name = models.ForeignKey(Author)
class Meta:
app_cache = new_app_cache

View File

@ -7,7 +7,9 @@ from django.db import connection, DatabaseError, IntegrityError
from django.db.models.fields import IntegerField, TextField, CharField, SlugField
from django.db.models.fields.related import ManyToManyField, ForeignKey
from django.db.transaction import atomic
from .models import Author, AuthorWithM2M, Book, BookWithSlug, BookWithM2M, Tag, TagIndexed, TagM2MTest, TagUniqueRename, UniqueTest
from .models import (Author, AuthorWithM2M, Book, BookWithLongName,
BookWithSlug, BookWithM2M, Tag, TagIndexed, TagM2MTest, TagUniqueRename,
UniqueTest)
class SchemaTests(TransactionTestCase):
@ -21,7 +23,10 @@ class SchemaTests(TransactionTestCase):
available_apps = []
models = [Author, AuthorWithM2M, Book, BookWithSlug, BookWithM2M, Tag, TagIndexed, TagM2MTest, TagUniqueRename, UniqueTest]
models = [
Author, AuthorWithM2M, Book, BookWithLongName, BookWithSlug,
BookWithM2M, Tag, TagIndexed, TagM2MTest, TagUniqueRename, UniqueTest,
]
# Utility functions
@ -659,3 +664,18 @@ class SchemaTests(TransactionTestCase):
raise SomeError
except SomeError:
self.assertFalse(connection.in_atomic_block)
def test_foreign_key_index_long_names_regression(self):
"""
Regression test for #21497. Only affects databases that supports
foreign keys.
"""
# Create the table
with connection.schema_editor() as editor:
editor.create_model(Author)
editor.create_model(BookWithLongName)
# Ensure the table is there and has the right index
self.assertIn(
"author_foreign_key_with_really_long_field_name_id",
connection.introspection.get_indexes(connection.cursor(), BookWithLongName._meta.db_table),
)