@@ -910,6 +910,41 @@ def test_when_collecting_only(self):
910910 == 'ALTER TABLE "example_app_intmodel" ADD CONSTRAINT "unique_int_field" UNIQUE USING INDEX "unique_int_field";'
911911 )
912912
913+ @pytest .mark .django_db (transaction = True )
914+ def test_when_collecting_only_reversed (self ):
915+ # Prove that the constraint exists before the operation removes it.
916+ with connection .cursor () as cursor :
917+ cursor .execute (
918+ psycopg_sql .SQL (operations .ConstraintQueries .CHECK_EXISTING_CONSTRAINT )
919+ .format (constraint_name = psycopg_sql .Literal ("unique_char_field" ))
920+ .as_string (cursor .connection )
921+ )
922+ assert cursor .fetchone ()
923+
924+ project_state = ProjectState ()
925+ project_state .add_model (ModelState .from_model (CharModel ))
926+ new_state = project_state .clone ()
927+
928+ operation = operations .SaferAddUniqueConstraint (
929+ model_name = "charmodel" ,
930+ constraint = UniqueConstraint (
931+ fields = ("char_field" ,),
932+ name = "unique_char_field" ,
933+ ),
934+ )
935+
936+ with connection .schema_editor (atomic = False , collect_sql = True ) as editor :
937+ with utils .CaptureQueriesContext (connection ) as queries :
938+ operation .database_backwards (
939+ self .app_label , editor , from_state = project_state , to_state = new_state
940+ )
941+
942+ assert len (editor .collected_sql ) == 1
943+ assert len (queries ) == 0
944+ assert editor .collected_sql [0 ] == (
945+ 'ALTER TABLE "example_app_charmodel" DROP CONSTRAINT "unique_char_field";'
946+ )
947+
913948 # Disable the overall test transaction because a unique concurrent index
914949 # creation followed by a constraint addition cannot be triggered/tested
915950 # inside of a transaction.
@@ -1576,6 +1611,38 @@ def test_when_not_allowed_to_migrate_by_the_router(self):
15761611 # the router.
15771612 assert len (queries ) == 0
15781613
1614+ @pytest .mark .django_db (transaction = True )
1615+ def test_when_collecting_only (self ):
1616+ # Prove that the constraint exists before the operation removes it.
1617+ with connection .cursor () as cursor :
1618+ cursor .execute (
1619+ psycopg_sql .SQL (operations .ConstraintQueries .CHECK_EXISTING_CONSTRAINT )
1620+ .format (constraint_name = psycopg_sql .Literal ("unique_char_field" ))
1621+ .as_string (cursor .connection )
1622+ )
1623+ assert cursor .fetchone ()
1624+
1625+ project_state = ProjectState ()
1626+ project_state .add_model (ModelState .from_model (CharModel ))
1627+ new_state = project_state .clone ()
1628+
1629+ operation = operations .SaferRemoveUniqueConstraint (
1630+ model_name = "charmodel" ,
1631+ name = "unique_char_field" ,
1632+ )
1633+
1634+ with connection .schema_editor (atomic = False , collect_sql = True ) as editor :
1635+ with utils .CaptureQueriesContext (connection ) as queries :
1636+ operation .database_forwards (
1637+ self .app_label , editor , from_state = project_state , to_state = new_state
1638+ )
1639+
1640+ assert len (editor .collected_sql ) == 1
1641+ assert len (queries ) == 0
1642+ assert editor .collected_sql [0 ] == (
1643+ 'ALTER TABLE "example_app_charmodel" DROP CONSTRAINT "unique_char_field";'
1644+ )
1645+
15791646 @pytest .mark .django_db (transaction = True )
15801647 def test_does_nothing_if_constraint_does_not_exist (self ):
15811648 # Remove the constraint so that the migration becomes a noop.
0 commit comments