summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorSalvo Polizzi <salvopolizzi03@gmail.com>2024-11-28 13:52:58 +0100
committerSarah Boyce <42296566+sarahboyce@users.noreply.github.com>2024-11-28 17:40:52 +0100
commitb82f80906a563741e34aecac537b53c19945a44f (patch)
tree7c043cbeeb3daf548fcc056a8114b89717e1675c /tests
parentb92511b47475ce7fa1626d7d8c6180ae84bf0a19 (diff)
Fixed #35038 -- Created AlterConstraint operation.
Diffstat (limited to 'tests')
-rw-r--r--tests/migrations/test_autodetector.py65
-rw-r--r--tests/migrations/test_operations.py75
-rw-r--r--tests/migrations/test_optimizer.py74
3 files changed, 214 insertions, 0 deletions
diff --git a/tests/migrations/test_autodetector.py b/tests/migrations/test_autodetector.py
index d93114564a..de62170eb3 100644
--- a/tests/migrations/test_autodetector.py
+++ b/tests/migrations/test_autodetector.py
@@ -2969,6 +2969,71 @@ class AutodetectorTests(BaseAutodetectorTests):
["CreateModel", "AddField", "AddIndex"],
)
+ def test_alter_constraint(self):
+ book_constraint = models.CheckConstraint(
+ condition=models.Q(title__contains="title"),
+ name="title_contains_title",
+ )
+ book_altered_constraint = models.CheckConstraint(
+ condition=models.Q(title__contains="title"),
+ name="title_contains_title",
+ violation_error_code="error_code",
+ )
+ author_altered_constraint = models.CheckConstraint(
+ condition=models.Q(name__contains="Bob"),
+ name="name_contains_bob",
+ violation_error_message="Name doesn't contain Bob",
+ )
+
+ book_check_constraint = copy.deepcopy(self.book)
+ book_check_constraint_with_error_message = copy.deepcopy(self.book)
+ author_name_check_constraint_with_error_message = copy.deepcopy(
+ self.author_name_check_constraint
+ )
+
+ book_check_constraint.options = {"constraints": [book_constraint]}
+ book_check_constraint_with_error_message.options = {
+ "constraints": [book_altered_constraint]
+ }
+ author_name_check_constraint_with_error_message.options = {
+ "constraints": [author_altered_constraint]
+ }
+
+ changes = self.get_changes(
+ [self.author_name_check_constraint, book_check_constraint],
+ [
+ author_name_check_constraint_with_error_message,
+ book_check_constraint_with_error_message,
+ ],
+ )
+
+ self.assertNumberMigrations(changes, "testapp", 1)
+ self.assertOperationTypes(changes, "testapp", 0, ["AlterConstraint"])
+ self.assertOperationAttributes(
+ changes,
+ "testapp",
+ 0,
+ 0,
+ model_name="author",
+ name="name_contains_bob",
+ constraint=author_altered_constraint,
+ )
+
+ self.assertNumberMigrations(changes, "otherapp", 1)
+ self.assertOperationTypes(changes, "otherapp", 0, ["AlterConstraint"])
+ self.assertOperationAttributes(
+ changes,
+ "otherapp",
+ 0,
+ 0,
+ model_name="book",
+ name="title_contains_title",
+ constraint=book_altered_constraint,
+ )
+ self.assertMigrationDependencies(
+ changes, "otherapp", 0, [("testapp", "auto_1")]
+ )
+
def test_remove_constraints(self):
"""Test change detection of removed constraints."""
changes = self.get_changes(
diff --git a/tests/migrations/test_operations.py b/tests/migrations/test_operations.py
index 3ac813b899..da0ec93dcd 100644
--- a/tests/migrations/test_operations.py
+++ b/tests/migrations/test_operations.py
@@ -4366,6 +4366,81 @@ class OperationTests(OperationTestBase):
{"model_name": "Pony", "name": "test_remove_constraint_pony_pink_gt_2"},
)
+ def test_alter_constraint(self):
+ constraint = models.UniqueConstraint(
+ fields=["pink"], name="test_alter_constraint_pony_fields_uq"
+ )
+ project_state = self.set_up_test_model(
+ "test_alterconstraint", constraints=[constraint]
+ )
+
+ new_state = project_state.clone()
+ violation_error_message = "Pink isn't unique"
+ uq_constraint = models.UniqueConstraint(
+ fields=["pink"],
+ name="test_alter_constraint_pony_fields_uq",
+ violation_error_message=violation_error_message,
+ )
+ uq_operation = migrations.AlterConstraint(
+ "Pony", "test_alter_constraint_pony_fields_uq", uq_constraint
+ )
+ self.assertEqual(
+ uq_operation.describe(),
+ "Alter constraint test_alter_constraint_pony_fields_uq on Pony",
+ )
+ self.assertEqual(
+ uq_operation.formatted_description(),
+ "~ Alter constraint test_alter_constraint_pony_fields_uq on Pony",
+ )
+ self.assertEqual(
+ uq_operation.migration_name_fragment,
+ "alter_pony_test_alter_constraint_pony_fields_uq",
+ )
+
+ uq_operation.state_forwards("test_alterconstraint", new_state)
+ self.assertEqual(
+ project_state.models["test_alterconstraint", "pony"]
+ .options["constraints"][0]
+ .violation_error_message,
+ "Constraint ā€œ%(name)sā€ is violated.",
+ )
+ self.assertEqual(
+ new_state.models["test_alterconstraint", "pony"]
+ .options["constraints"][0]
+ .violation_error_message,
+ violation_error_message,
+ )
+
+ with connection.schema_editor() as editor, self.assertNumQueries(0):
+ uq_operation.database_forwards(
+ "test_alterconstraint", editor, project_state, new_state
+ )
+ self.assertConstraintExists(
+ "test_alterconstraint_pony",
+ "test_alter_constraint_pony_fields_uq",
+ value=False,
+ )
+ with connection.schema_editor() as editor, self.assertNumQueries(0):
+ uq_operation.database_backwards(
+ "test_alterconstraint", editor, project_state, new_state
+ )
+ self.assertConstraintExists(
+ "test_alterconstraint_pony",
+ "test_alter_constraint_pony_fields_uq",
+ value=False,
+ )
+ definition = uq_operation.deconstruct()
+ self.assertEqual(definition[0], "AlterConstraint")
+ self.assertEqual(definition[1], [])
+ self.assertEqual(
+ definition[2],
+ {
+ "model_name": "Pony",
+ "name": "test_alter_constraint_pony_fields_uq",
+ "constraint": uq_constraint,
+ },
+ )
+
def test_add_partial_unique_constraint(self):
project_state = self.set_up_test_model("test_addpartialuniqueconstraint")
partial_unique_constraint = models.UniqueConstraint(
diff --git a/tests/migrations/test_optimizer.py b/tests/migrations/test_optimizer.py
index 0a40b50edc..a871e67a45 100644
--- a/tests/migrations/test_optimizer.py
+++ b/tests/migrations/test_optimizer.py
@@ -1232,6 +1232,80 @@ class OptimizerTests(OptimizerTestBase):
],
)
+ def test_multiple_alter_constraints(self):
+ gt_constraint_violation_msg_added = models.CheckConstraint(
+ condition=models.Q(pink__gt=2),
+ name="pink_gt_2",
+ violation_error_message="ERROR",
+ )
+ gt_constraint_violation_msg_altered = models.CheckConstraint(
+ condition=models.Q(pink__gt=2),
+ name="pink_gt_2",
+ violation_error_message="error",
+ )
+ self.assertOptimizesTo(
+ [
+ migrations.AlterConstraint(
+ "Pony", "pink_gt_2", gt_constraint_violation_msg_added
+ ),
+ migrations.AlterConstraint(
+ "Pony", "pink_gt_2", gt_constraint_violation_msg_altered
+ ),
+ ],
+ [
+ migrations.AlterConstraint(
+ "Pony", "pink_gt_2", gt_constraint_violation_msg_altered
+ )
+ ],
+ )
+ other_constraint_violation_msg = models.CheckConstraint(
+ condition=models.Q(weight__gt=3),
+ name="pink_gt_3",
+ violation_error_message="error",
+ )
+ self.assertDoesNotOptimize(
+ [
+ migrations.AlterConstraint(
+ "Pony", "pink_gt_2", gt_constraint_violation_msg_added
+ ),
+ migrations.AlterConstraint(
+ "Pony", "pink_gt_3", other_constraint_violation_msg
+ ),
+ ]
+ )
+
+ def test_alter_remove_constraint(self):
+ self.assertOptimizesTo(
+ [
+ migrations.AlterConstraint(
+ "Pony",
+ "pink_gt_2",
+ models.CheckConstraint(
+ condition=models.Q(pink__gt=2), name="pink_gt_2"
+ ),
+ ),
+ migrations.RemoveConstraint("Pony", "pink_gt_2"),
+ ],
+ [migrations.RemoveConstraint("Pony", "pink_gt_2")],
+ )
+
+ def test_add_alter_constraint(self):
+ constraint = models.CheckConstraint(
+ condition=models.Q(pink__gt=2), name="pink_gt_2"
+ )
+ constraint_with_error = models.CheckConstraint(
+ condition=models.Q(pink__gt=2),
+ name="pink_gt_2",
+ violation_error_message="error",
+ )
+ self.assertOptimizesTo(
+ [
+ migrations.AddConstraint("Pony", constraint),
+ migrations.AlterConstraint("Pony", "pink_gt_2", constraint_with_error),
+ ],
+ [migrations.AddConstraint("Pony", constraint_with_error)],
+ )
+
def test_create_model_add_index(self):
self.assertOptimizesTo(
[