summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Charette <charette.s@gmail.com>2016-12-17 15:06:47 -0500
committerSimon Charette <charette.s@gmail.com>2016-12-24 13:53:11 -0500
commitcd7efa20338cb6f3ede4780e00590c0a6dd48ca2 (patch)
treef38adc44e59a35313c18e5f9cb1cb21467c900f8
parenta4cac1720034920351291359d0bb2177d8c8a4d5 (diff)
Fixed #25492 -- Checked deferred foreign key constraints before dropping them.
This allows running foreign key data and schema altering operations in the same migration on PostgreSQL. Thanks Tim for review.
-rw-r--r--django/db/backends/postgresql/schema.py4
-rw-r--r--tests/schema/tests.py17
2 files changed, 21 insertions, 0 deletions
diff --git a/django/db/backends/postgresql/schema.py b/django/db/backends/postgresql/schema.py
index 1afb85d468..bffa8bd45b 100644
--- a/django/db/backends/postgresql/schema.py
+++ b/django/db/backends/postgresql/schema.py
@@ -15,6 +15,10 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor):
sql_create_varchar_index = "CREATE INDEX %(name)s ON %(table)s (%(columns)s varchar_pattern_ops)%(extra)s"
sql_create_text_index = "CREATE INDEX %(name)s ON %(table)s (%(columns)s text_pattern_ops)%(extra)s"
+ # Setting the constraint to IMMEDIATE runs any deferred checks to allow
+ # dropping it in the same transaction.
+ sql_delete_fk = "SET CONSTRAINTS %(name)s IMMEDIATE; ALTER TABLE %(table)s DROP CONSTRAINT %(name)s"
+
def quote_value(self, value):
return psycopg2.extensions.adapt(value)
diff --git a/tests/schema/tests.py b/tests/schema/tests.py
index e8cb1996cb..cf96e4163e 100644
--- a/tests/schema/tests.py
+++ b/tests/schema/tests.py
@@ -532,6 +532,23 @@ class SchemaTests(TransactionTestCase):
with connection.schema_editor() as editor:
editor.alter_field(Note, old_field, new_field, strict=True)
+ @skipUnlessDBFeature('can_defer_constraint_checks', 'can_rollback_ddl')
+ def test_alter_fk_checks_deferred_constraints(self):
+ """
+ #25492 - Altering a foreign key's structure and data in the same
+ transaction.
+ """
+ with connection.schema_editor() as editor:
+ editor.create_model(Node)
+ old_field = Node._meta.get_field('parent')
+ new_field = ForeignKey(Node, CASCADE)
+ new_field.set_attributes_from_name('parent')
+ parent = Node.objects.create()
+ with connection.schema_editor() as editor:
+ # Update the parent FK to create a deferred constraint check.
+ Node.objects.update(parent=parent)
+ editor.alter_field(Node, old_field, new_field, strict=True)
+
def test_alter_text_field_to_date_field(self):
"""
#25002 - Test conversion of text field to date field.