Commit 1c57d7e7 authored by Tim Graham's avatar Tim Graham
Browse files

[1.8.x] Fixed #24893 -- Fixed lack of unique constraint when changing a field...

[1.8.x] Fixed #24893 -- Fixed lack of unique constraint when changing a field from primary_key=True to unique=True

Backport of e1e6399c from master
parent 8911d2e2
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -659,7 +659,9 @@ class BaseDatabaseSchemaEditor(object):
            for sql, params in post_actions:
                self.execute(sql, params)
        # Added a unique?
        if not old_field.unique and new_field.unique:
        if (not old_field.unique and new_field.unique) or (
            old_field.primary_key and not new_field.primary_key and new_field.unique
        ):
            self.execute(self._create_unique_sql(model, [new_field.column]))
        # Added an index?
        if (not old_field.db_index and new_field.db_index and
+3 −0
Original line number Diff line number Diff line
@@ -34,3 +34,6 @@ Bugfixes

* Fixed quoting of SQL when renaming a field to ``AutoField`` in PostgreSQL
  (:ticket:`24892`).

* Fixed lack of unique constraint when changing a field from
  ``primary_key=True`` to ``unique=True`` (:ticket:`24893`).
+1 −0
Original line number Diff line number Diff line
@@ -82,6 +82,7 @@ class BookWithSlug(models.Model):

class IntegerPK(models.Model):
    i = models.IntegerField(primary_key=True)
    j = models.IntegerField(unique=True)

    class Meta:
        apps = new_apps
+39 −0
Original line number Diff line number Diff line
@@ -745,6 +745,45 @@ class SchemaTests(TransactionTestCase):
        with connection.schema_editor() as editor:
            editor.alter_field(IntegerPK, old_field, new_field, strict=True)

    def test_alter_int_pk_to_int_unique(self):
        """
        Should be able to rename an IntegerField(primary_key=True) to
        IntegerField(unique=True).
        """
        class IntegerUnique(Model):
            i = IntegerField(unique=True)
            j = IntegerField(primary_key=True)

            class Meta:
                app_label = 'schema'
                apps = new_apps
                db_table = 'INTEGERPK'

        with connection.schema_editor() as editor:
            editor.create_model(IntegerPK)

        # model requires a new PK
        old_field = IntegerPK._meta.get_field('j')
        new_field = IntegerField(primary_key=True)
        new_field.model = IntegerPK
        new_field.set_attributes_from_name('j')

        with connection.schema_editor() as editor:
            editor.alter_field(IntegerPK, old_field, new_field, strict=True)

        old_field = IntegerPK._meta.get_field('i')
        new_field = IntegerField(unique=True)
        new_field.model = IntegerPK
        new_field.set_attributes_from_name('i')

        with connection.schema_editor() as editor:
            editor.alter_field(IntegerPK, old_field, new_field, strict=True)

        # Ensure unique constraint works.
        IntegerUnique.objects.create(i=1, j=1)
        with self.assertRaises(IntegrityError):
            IntegerUnique.objects.create(i=1, j=2)

    def test_rename(self):
        """
        Tests simple altering of fields