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> David Blewett <david@dawninglight.net>
Artem Gnilov <boobsd@gmail.com> Artem Gnilov <boobsd@gmail.com>
Eric Boersma <eric.boersma@gmail.com> Eric Boersma <eric.boersma@gmail.com>
Joel Bohman <mail@jbohman.com>
Matías Bordese Matías Bordese
Nate Bragg <jonathan.bragg@alum.rpi.edu> Nate Bragg <jonathan.bragg@alum.rpi.edu>
Sean Brant 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.backends.utils import truncate_name
from django.db.models.fields.related import ManyToManyField from django.db.models.fields.related import ManyToManyField
from django.db.transaction import atomic from django.db.transaction import atomic
from django.utils.encoding import force_bytes
from django.utils.log import getLogger from django.utils.log import getLogger
from django.utils.six.moves import reduce from django.utils.six.moves import reduce
from django.utils.six import callable from django.utils.six import callable
@ -703,7 +704,7 @@ class BaseDatabaseSchemaEditor(object):
index_name = index_name[1:] index_name = index_name[1:]
# If it's STILL too long, just hash it down # If it's STILL too long, just hash it down
if len(index_name) > self.connection.features.max_index_name_length: 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 # It can't start with a number on Oracle, so prepend D if we need to
if index_name[0].isdigit(): if index_name[0].isdigit():
index_name = "D%s" % index_name[:-1] index_name = "D%s" % index_name[:-1]

View File

@ -95,3 +95,10 @@ class UniqueTest(models.Model):
class Meta: class Meta:
app_cache = new_app_cache app_cache = new_app_cache
unique_together = ["year", "slug"] 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 import IntegerField, TextField, CharField, SlugField
from django.db.models.fields.related import ManyToManyField, ForeignKey from django.db.models.fields.related import ManyToManyField, ForeignKey
from django.db.transaction import atomic 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): class SchemaTests(TransactionTestCase):
@ -21,7 +23,10 @@ class SchemaTests(TransactionTestCase):
available_apps = [] 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 # Utility functions
@ -659,3 +664,18 @@ class SchemaTests(TransactionTestCase):
raise SomeError raise SomeError
except SomeError: except SomeError:
self.assertFalse(connection.in_atomic_block) 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),
)