1
0
mirror of https://github.com/django/django.git synced 2024-12-23 01:25:58 +00:00

Fixed #28646 -- Prevented duplicate index error on PostgreSQL.

This commit is contained in:
Ben Cail 2024-10-31 17:00:13 -04:00
parent 8864125d1f
commit fdf580d9b5
2 changed files with 59 additions and 8 deletions

View File

@ -258,6 +258,25 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor):
model, old_field, new_field, new_type, old_collation, new_collation
)
def _new_index_should_be_added(self, old_field, new_field):
return not (old_field.db_index or old_field.unique) and (
new_field.db_index or new_field.unique
)
def _deleted_index_should_be_recreated(
self, old_field, new_field, old_type, new_type
):
if (
not old_field.unique
and (
not new_field.db_index
or (new_field.unique and not new_field.primary_key)
)
) or (
self._is_changing_type_of_indexed_text_column(old_field, old_type, new_type)
):
return True
def _alter_field(
self,
model,
@ -280,14 +299,10 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor):
strict,
)
# Added an index? Create any PostgreSQL-specific indexes.
if (
(not (old_field.db_index or old_field.unique) and new_field.db_index)
or (not old_field.unique and new_field.unique)
or (
self._is_changing_type_of_indexed_text_column(
old_field, old_type, new_type
)
)
if self._new_index_should_be_added(
old_field, new_field
) or self._deleted_index_should_be_recreated(
old_field, new_field, old_type, new_type
):
like_index_statement = self._create_like_index_sql(model, new_field)
if like_index_statement is not None:

View File

@ -6213,6 +6213,42 @@ class OperationTests(OperationTestBase):
self.assertEqual(pony_new.static, 2)
class PrimaryKeyOperations(OperationTestBase):
def test_slugfields_change_primary_key_operations(self):
# Create a model with two fields
operation1 = migrations.CreateModel(
"SimpleModel",
[
("field1", models.SlugField(max_length=20, primary_key=True)),
("field2", models.SlugField(max_length=20)),
],
)
# Drop field1 primary key constraint - this doesn't fail
operation2 = migrations.AlterField(
"SimpleModel",
"field1",
models.SlugField(max_length=20, primary_key=False),
)
# Add a primary key constraint to field2 - this fails
operation3 = migrations.AlterField(
"SimpleModel",
"field2",
models.SlugField(max_length=20, primary_key=True),
)
project_state = ProjectState()
with connection.schema_editor() as editor:
new_state = project_state.clone()
operation1.state_forwards("migrtest", new_state)
operation1.database_forwards("migrtest", editor, project_state, new_state)
project_state, new_state = new_state, new_state.clone()
operation2.state_forwards("migrtest", new_state)
operation2.database_forwards("migrtest", editor, project_state, new_state)
project_state, new_state = new_state, new_state.clone()
operation3.state_forwards("migrtest", new_state)
operation3.database_forwards("migrtest", editor, project_state, new_state)
class SwappableOperationTests(OperationTestBase):
"""
Key operations ignore swappable models