Fixed #23009: Shorten FK identifiers in add_field and make consistent

This commit is contained in:
Andrew Godwin 2014-07-21 10:50:21 +01:00
parent dcb4ed5170
commit 7dacc6ae46
3 changed files with 41 additions and 14 deletions

View File

@ -435,11 +435,7 @@ class BaseDatabaseSchemaEditor(object):
to_column = field.rel.to._meta.get_field(field.rel.field_name).column
self.deferred_sql.append(
self.sql_create_fk % {
"name": self.quote_name('%s_refs_%s_%x' % (
field.column,
to_column,
abs(hash((model._meta.db_table, to_table)))
)),
"name": self._create_index_name(model, [field.column], suffix="_fk_%s_%s" % (to_table, to_column)),
"table": self.quote_name(model._meta.db_table),
"column": self.quote_name(field.column),
"to_table": self.quote_name(to_table),
@ -737,13 +733,15 @@ class BaseDatabaseSchemaEditor(object):
)
# Does it have a foreign key?
if new_field.rel:
to_table = new_field.rel.to._meta.db_table
to_column = new_field.rel.get_related_field().column
self.execute(
self.sql_create_fk % {
"table": self.quote_name(model._meta.db_table),
"name": self._create_index_name(model, [new_field.column], suffix="_fk"),
"name": self._create_index_name(model, [new_field.column], suffix="_fk_%s_%s" % (to_table, to_column)),
"column": self.quote_name(new_field.column),
"to_table": self.quote_name(new_field.rel.to._meta.db_table),
"to_column": self.quote_name(new_field.rel.get_related_field().column),
"to_table": self.quote_name(to_table),
"to_column": self.quote_name(to_column),
}
)
# Rebuild FKs that pointed to us if we previously had to drop them

View File

@ -129,8 +129,16 @@ class UniqueTest(models.Model):
unique_together = ["year", "slug"]
class AuthorWithEvenLongerName(models.Model):
name = models.CharField(max_length=255)
height = models.PositiveIntegerField(null=True, blank=True)
class Meta:
apps = new_apps
class BookWithLongName(models.Model):
author_foreign_key_with_really_long_field_name = models.ForeignKey(Author)
author_foreign_key_with_really_long_field_name = models.ForeignKey(AuthorWithEvenLongerName)
class Meta:
apps = new_apps

View File

@ -9,7 +9,8 @@ from django.db.models.fields.related import ManyToManyField, ForeignKey
from django.db.transaction import atomic
from .models import (Author, AuthorWithM2M, Book, BookWithLongName,
BookWithSlug, BookWithM2M, Tag, TagIndexed, TagM2MTest, TagUniqueRename,
UniqueTest, Thing, TagThrough, BookWithM2MThrough, AuthorTag, AuthorWithM2MThrough)
UniqueTest, Thing, TagThrough, BookWithM2MThrough, AuthorTag, AuthorWithM2MThrough,
AuthorWithEvenLongerName)
class SchemaTests(TransactionTestCase):
@ -26,7 +27,7 @@ class SchemaTests(TransactionTestCase):
models = [
Author, AuthorWithM2M, Book, BookWithLongName, BookWithSlug,
BookWithM2M, Tag, TagIndexed, TagM2MTest, TagUniqueRename, UniqueTest,
Thing, TagThrough, BookWithM2MThrough
Thing, TagThrough, BookWithM2MThrough, AuthorWithEvenLongerName
]
# Utility functions
@ -846,14 +847,15 @@ class SchemaTests(TransactionTestCase):
except SomeError:
self.assertFalse(connection.in_atomic_block)
@unittest.skipUnless(connection.features.supports_foreign_keys, "No FK support")
def test_foreign_key_index_long_names_regression(self):
"""
Regression test for #21497. Only affects databases that supports
foreign keys.
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(AuthorWithEvenLongerName)
editor.create_model(BookWithLongName)
# Find the properly shortened column name
column_name = connection.ops.quote_name("author_foreign_key_with_really_long_field_name_id")
@ -864,6 +866,25 @@ class SchemaTests(TransactionTestCase):
self.get_indexes(BookWithLongName._meta.db_table),
)
@unittest.skipUnless(connection.features.supports_foreign_keys, "No FK support")
def test_add_foreign_key_long_names(self):
"""
Regression test for #23009.
Only affects databases that supports foreign keys.
"""
# Create the initial tables
with connection.schema_editor() as editor:
editor.create_model(AuthorWithEvenLongerName)
editor.create_model(BookWithLongName)
# Add a second FK, this would fail due to long ref name before the fix
new_field = ForeignKey(AuthorWithEvenLongerName, related_name="something")
new_field.set_attributes_from_name("author_other_really_long_named_i_mean_so_long_fk")
with connection.schema_editor() as editor:
editor.add_field(
BookWithLongName,
new_field,
)
def test_creation_deletion_reserved_names(self):
"""
Tries creating a model's table, and then deleting it when it has a