summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTim Graham <timograham@gmail.com>2016-01-07 20:06:58 -0500
committerTim Graham <timograham@gmail.com>2016-01-08 14:20:53 -0500
commit3d324b9614afa1e9b391b30f6f21d2f65fa8ac90 (patch)
tree2571e12e0e246c45f52ee8d01d57fbd0a756d08c
parent20c8cc2bf54a3ee6ff2b9cbb79b47f08cbfc1d39 (diff)
[1.9.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 56aaae58a746eb39d5e92ba60f59f4c750a8e1a8 from master
-rw-r--r--django/db/backends/postgresql/schema.py4
-rw-r--r--docs/releases/1.8.9.txt5
-rw-r--r--docs/releases/1.9.2.txt5
-rw-r--r--tests/schema/tests.py60
4 files changed, 72 insertions, 2 deletions
diff --git a/django/db/backends/postgresql/schema.py b/django/db/backends/postgresql/schema.py
index cc31aadf0a..8d4dc871cd 100644
--- a/django/db/backends/postgresql/schema.py
+++ b/django/db/backends/postgresql/schema.py
@@ -110,13 +110,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:
diff --git a/docs/releases/1.8.9.txt b/docs/releases/1.8.9.txt
index 5525eca84a..080d6506e8 100644
--- a/docs/releases/1.8.9.txt
+++ b/docs/releases/1.8.9.txt
@@ -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`).
diff --git a/docs/releases/1.9.2.txt b/docs/releases/1.9.2.txt
index ffe5030d9e..d7857052ad 100644
--- a/docs/releases/1.9.2.txt
+++ b/docs/releases/1.9.2.txt
@@ -25,3 +25,8 @@ Bugfixes
* Fixed a regression in the admin's edit related model popup that caused an
escaped value to be displayed in the select dropdown of the parent window
(:ticket:`25997`).
+
+* 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`).
diff --git a/tests/schema/tests.py b/tests/schema/tests.py
index 7e17402f70..dfd0659d34 100644
--- a/tests/schema/tests.py
+++ b/tests/schema/tests.py
@@ -1757,3 +1757,63 @@ 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(
+ self.get_constraints_for_column(BookWithoutAuthor, 'title'),
+ ['schema_book_d5d3db17', 'schema_book_title_2dfb2dff_like']
+ )
+ # 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(
+ self.get_constraints_for_column(BookWithoutAuthor, 'title'),
+ ['schema_book_d5d3db17', 'schema_book_title_2dfb2dff_like', 'schema_book_title_2dfb2dff_uniq']
+ )
+ # 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(
+ self.get_constraints_for_column(BookWithoutAuthor, 'title'),
+ ['schema_book_d5d3db17', 'schema_book_title_2dfb2dff_like', 'schema_book_title_2dfb2dff_uniq']
+ )
+
+ @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(
+ self.get_constraints_for_column(Tag, 'slug'),
+ ['schema_tag_slug_2c418ba3_like', 'schema_tag_slug_key']
+ )
+ # 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(
+ self.get_constraints_for_column(Tag, 'slug'),
+ ['schema_tag_slug_2c418ba3_like', 'schema_tag_slug_key']
+ )
+ # 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(
+ self.get_constraints_for_column(Tag, 'slug'),
+ ['schema_tag_slug_2c418ba3_like', 'schema_tag_slug_key']
+ )