Commit 7dacc6ae authored by Andrew Godwin's avatar Andrew Godwin
Browse files

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

parent dcb4ed51
Loading
Loading
Loading
Loading
+6 −8
Original line number Diff line number Diff line
@@ -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
+9 −1
Original line number Diff line number Diff line
@@ -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
+26 −5
Original line number Diff line number Diff line
@@ -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