Commit f8c3d38c authored by Tim Graham's avatar Tim Graham
Browse files

[1.8.x] Fixed #26034 -- Fixed incorrect index handling on PostgreSQL on...

[1.8.x] Fixed #26034 -- Fixed incorrect index handling on PostgreSQL on Char/TextField with unique=True and db_index=True.

Thanks Simon Charette for review.

Backport of 56aaae58 from master
parent fe5d37f9
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -107,13 +107,13 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor):
            new_db_params, strict,
        )
        # Added an index? Create any PostgreSQL-specific indexes.
        if ((not old_field.db_index and new_field.db_index) or (not old_field.unique and new_field.unique)):
        if not old_field.db_index and not old_field.unique and (new_field.db_index or new_field.unique):
            like_index_statement = self._create_like_index_sql(model, new_field)
            if like_index_statement is not None:
                self.execute(like_index_statement)

        # Removed an index? Drop any PostgreSQL-specific indexes.
        if ((not new_field.db_index and old_field.db_index) or (not new_field.unique and old_field.unique)):
        if (old_field.db_index or old_field.unique) and not (new_field.db_index or new_field.unique):
            index_to_remove = self._create_index_name(model, [old_field.column], suffix='_like')
            index_names = self._constraint_names(model, [old_field.column], index=True)
            for index_name in index_names:
+5 −0
Original line number Diff line number Diff line
@@ -18,3 +18,8 @@ Bugfixes
* Fixed a regression that caused the incorrect day to be selected when opening
  the admin calendar widget for timezones from GMT+0100 to GMT+1200
  (:ticket:`24980`).

* Fixed incorrect index handling in migrations on PostgreSQL when adding
  ``db_index=True`` or ``unique=True`` to a ``CharField`` or ``TextField`` that
  already had the other specified, or when removing one of them from a field
  that had both (:ticket:`26034`).
+42 −0
Original line number Diff line number Diff line
@@ -1592,3 +1592,45 @@ class SchemaTests(TransactionTestCase):
        with connection.schema_editor() as editor:
            editor.alter_field(Note, new_field, old_field, strict=True)
        self.assertEqual(self.get_constraints_for_column(Note, 'info'), [])

    @unittest.skipUnless(connection.vendor == 'postgresql', "PostgreSQL specific")
    def test_alter_field_add_unique_to_charfield_with_db_index(self):
        # Create the table and verify initial indexes.
        with connection.schema_editor() as editor:
            editor.create_model(BookWithoutAuthor)
        self.assertEqual(len(self.get_constraints_for_column(BookWithoutAuthor, 'title')), 2)
        # Alter to add unique=True (should add 1 index)
        old_field = BookWithoutAuthor._meta.get_field('title')
        new_field = CharField(max_length=100, db_index=True, unique=True)
        new_field.set_attributes_from_name('title')
        with connection.schema_editor() as editor:
            editor.alter_field(BookWithoutAuthor, old_field, new_field, strict=True)
        self.assertEqual(len(self.get_constraints_for_column(BookWithoutAuthor, 'title')), 3)
        # Alter to remove unique=True (should drop unique index) # XXX: bug!
        old_field = BookWithoutAuthor._meta.get_field('title')
        new_field = CharField(max_length=100, db_index=True)
        new_field.set_attributes_from_name('title')
        with connection.schema_editor() as editor:
            editor.alter_field(BookWithoutAuthor, old_field, new_field, strict=True)
        self.assertEqual(len(self.get_constraints_for_column(BookWithoutAuthor, 'title')), 3)

    @unittest.skipUnless(connection.vendor == 'postgresql', "PostgreSQL specific")
    def test_alter_field_add_db_index_to_charfield_with_unique(self):
        # Create the table and verify initial indexes.
        with connection.schema_editor() as editor:
            editor.create_model(Tag)
        self.assertEqual(len(self.get_constraints_for_column(Tag, 'slug')), 2)
        # Alter to add db_index=True
        old_field = Tag._meta.get_field('slug')
        new_field = SlugField(db_index=True, unique=True)
        new_field.set_attributes_from_name('slug')
        with connection.schema_editor() as editor:
            editor.alter_field(Tag, old_field, new_field, strict=True)
        self.assertEqual(len(self.get_constraints_for_column(Tag, 'slug')), 2)
        # Alter to remove db_index=True
        old_field = Tag._meta.get_field('slug')
        new_field = SlugField(unique=True)
        new_field.set_attributes_from_name('slug')
        with connection.schema_editor() as editor:
            editor.alter_field(Tag, old_field, new_field, strict=True)
        self.assertEqual(len(self.get_constraints_for_column(Tag, 'slug')), 2)