diff options
| author | Ben Cail <bcail@crossway.org> | 2024-02-01 16:08:42 -0500 |
|---|---|---|
| committer | Sarah Boyce <42296566+sarahboyce@users.noreply.github.com> | 2024-07-30 17:27:10 +0200 |
| commit | 9cf9c796be8dd53bc3b11355ff39d65c81d7be6d (patch) | |
| tree | 3d5e2c2a4bd8cdac02f079b2a62135e575f19687 /django | |
| parent | 7e00fee3bd3b780667f072325bdb69f29144c553 (diff) | |
Fixed #28646 -- Prevented duplicate index when unique is set to True on PostgreSQL.
Diffstat (limited to 'django')
| -rw-r--r-- | django/db/backends/base/schema.py | 4 | ||||
| -rw-r--r-- | django/db/backends/postgresql/schema.py | 38 |
2 files changed, 32 insertions, 10 deletions
diff --git a/django/db/backends/base/schema.py b/django/db/backends/base/schema.py index 3e38c56d50..f6b675339a 100644 --- a/django/db/backends/base/schema.py +++ b/django/db/backends/base/schema.py @@ -964,9 +964,7 @@ class BaseDatabaseSchemaEditor: fks_dropped.add((old_field.column,)) self.execute(self._delete_fk_sql(model, fk_name)) # Has unique been removed? - if old_field.unique and ( - not new_field.unique or self._field_became_primary_key(old_field, new_field) - ): + if old_field.unique and not old_field.primary_key and not new_field.unique: # Find the unique constraint for this field meta_constraint_names = { constraint.name for constraint in model._meta.constraints diff --git a/django/db/backends/postgresql/schema.py b/django/db/backends/postgresql/schema.py index 0c8548a5d6..c0a785c7e1 100644 --- a/django/db/backends/postgresql/schema.py +++ b/django/db/backends/postgresql/schema.py @@ -140,6 +140,13 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor): return sequence["name"] return None + def _is_changing_type_of_indexed_text_column(self, old_field, old_type, new_type): + return (old_field.db_index or old_field.unique) and ( + (old_type.startswith("varchar") and not new_type.startswith("varchar")) + or (old_type.startswith("text") and not new_type.startswith("text")) + or (old_type.startswith("citext") and not new_type.startswith("citext")) + ) + def _alter_column_type_sql( self, model, old_field, new_field, new_type, old_collation, new_collation ): @@ -147,11 +154,7 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor): # different type. old_db_params = old_field.db_parameters(connection=self.connection) old_type = old_db_params["type"] - if (old_field.db_index or old_field.unique) and ( - (old_type.startswith("varchar") and not new_type.startswith("varchar")) - or (old_type.startswith("text") and not new_type.startswith("text")) - or (old_type.startswith("citext") and not new_type.startswith("citext")) - ): + if self._is_changing_type_of_indexed_text_column(old_field, old_type, new_type): index_name = self._create_index_name( model._meta.db_table, [old_field.column], suffix="_like" ) @@ -255,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, @@ -277,8 +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 + 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: |
