|
18 | 18 | from django.db.transaction import TransactionManagementError
|
19 | 19 | from django.utils.encoding import force_str
|
20 | 20 |
|
| 21 | +from collections import defaultdict |
| 22 | + |
21 | 23 |
|
22 | 24 | class Statement(DjStatement):
|
23 | 25 | def __hash__(self):
|
@@ -68,6 +70,8 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor):
|
68 | 70 | sql_create_unique_null = "CREATE UNIQUE INDEX %(name)s ON %(table)s(%(columns)s) " \
|
69 | 71 | "WHERE %(columns)s IS NOT NULL"
|
70 | 72 |
|
| 73 | + _deferred_unique_indexes = defaultdict(list) |
| 74 | + |
71 | 75 | def _alter_column_default_sql(self, model, old_field, new_field, drop=False):
|
72 | 76 | """
|
73 | 77 | Hook to specialize column default alteration.
|
@@ -236,6 +240,12 @@ def alter_db_table(self, model, old_db_table, new_db_table):
|
236 | 240 |
|
237 | 241 | return super().alter_db_table(model, old_db_table, new_db_table)
|
238 | 242 |
|
| 243 | + def _delete_deferred_unique_indexes_for_field(self, field_name): |
| 244 | + deferred_statements = self._deferred_unique_indexes.get(field_name, []) |
| 245 | + for stmt in deferred_statements: |
| 246 | + if stmt in self.deferred_sql: |
| 247 | + self.deferred_sql.remove(stmt) |
| 248 | + |
239 | 249 | def _alter_field(self, model, old_field, new_field, old_type, new_type,
|
240 | 250 | old_db_params, new_db_params, strict=False):
|
241 | 251 | """Actually perform a "physical" (non-ManyToMany) field update."""
|
@@ -449,6 +459,7 @@ def _alter_field(self, model, old_field, new_field, old_type, new_type,
|
449 | 459 | )
|
450 | 460 | else:
|
451 | 461 | self.execute(self._create_unique_sql(model, [new_field.column]))
|
| 462 | + self._delete_deferred_unique_indexes_for_field(old_field) |
452 | 463 | # Added an index?
|
453 | 464 | # constraint will no longer be used in lieu of an index. The following
|
454 | 465 | # lines from the truth table show all True cases; the rest are False:
|
@@ -477,6 +488,7 @@ def _alter_field(self, model, old_field, new_field, old_type, new_type,
|
477 | 488 | )
|
478 | 489 | else:
|
479 | 490 | self.execute(self._create_unique_sql(model, columns=[old_field.column]))
|
| 491 | + self._delete_deferred_unique_indexes_for_field(old_field) |
480 | 492 | else:
|
481 | 493 | for fields in model._meta.unique_together:
|
482 | 494 | columns = [model._meta.get_field(field).column for field in fields]
|
@@ -644,9 +656,11 @@ def add_field(self, model, field):
|
644 | 656 | not field.many_to_many and field.null and field.unique):
|
645 | 657 |
|
646 | 658 | definition = definition.replace(' UNIQUE', '')
|
647 |
| - self.deferred_sql.append(self._create_index_sql( |
| 659 | + statement = self._create_index_sql( |
648 | 660 | model, [field], sql=self.sql_create_unique_null, suffix="_uniq"
|
649 |
| - )) |
| 661 | + ) |
| 662 | + self.deferred_sql.append(statement) |
| 663 | + self._deferred_unique_indexes[field].append(statement) |
650 | 664 |
|
651 | 665 | # Check constraints can go on the column SQL here
|
652 | 666 | db_params = field.db_parameters(connection=self.connection)
|
@@ -750,9 +764,11 @@ def create_model(self, model):
|
750 | 764 | not field.many_to_many and field.null and field.unique):
|
751 | 765 |
|
752 | 766 | definition = definition.replace(' UNIQUE', '')
|
753 |
| - self.deferred_sql.append(self._create_index_sql( |
| 767 | + statement = self._create_index_sql( |
754 | 768 | model, [field], sql=self.sql_create_unique_null, suffix="_uniq"
|
755 |
| - )) |
| 769 | + ) |
| 770 | + self.deferred_sql.append(statement) |
| 771 | + self._deferred_unique_indexes[field].append(statement) |
756 | 772 |
|
757 | 773 | # Check constraints can go on the column SQL here
|
758 | 774 | db_params = field.db_parameters(connection=self.connection)
|
|
0 commit comments