Fixed #32369 -- Fixed adding check constraints with pattern lookups and expressions as rhs.
This disables interpolation of constraint creation statements. Since Constraint.create_sql interpolates its parameters instead of deferring this responsibility to the backend connection it must disable connection level parameters interpolation.
This commit is contained in:
parent
90ddf46ef7
commit
42e8cf47c7
|
@ -360,6 +360,8 @@ class BaseDatabaseSchemaEditor:
|
|||
not self.connection.features.supports_expression_indexes
|
||||
):
|
||||
return None
|
||||
# Index.create_sql returns interpolated SQL which makes params=None a
|
||||
# necessity to avoid escaping attempts on execution.
|
||||
self.execute(index.create_sql(model, self), params=None)
|
||||
|
||||
def remove_index(self, model, index):
|
||||
|
@ -375,7 +377,9 @@ class BaseDatabaseSchemaEditor:
|
|||
"""Add a constraint to a model."""
|
||||
sql = constraint.create_sql(model, self)
|
||||
if sql:
|
||||
self.execute(sql)
|
||||
# Constraint.create_sql returns interpolated SQL which makes
|
||||
# params=None a necessity to avoid escaping attempts on execution.
|
||||
self.execute(sql, params=None)
|
||||
|
||||
def remove_constraint(self, model, constraint):
|
||||
"""Remove a constraint from a model."""
|
||||
|
|
|
@ -2145,6 +2145,7 @@ class OperationTests(OperationTestBase):
|
|||
fields=[
|
||||
('id', models.AutoField(primary_key=True)),
|
||||
('name', models.CharField(max_length=100)),
|
||||
('surname', models.CharField(max_length=100, default='')),
|
||||
('rebate', models.CharField(max_length=100)),
|
||||
],
|
||||
),
|
||||
|
@ -2178,6 +2179,19 @@ class OperationTests(OperationTestBase):
|
|||
Author.objects.create(name='Albert', rebate='10$')
|
||||
author = Author.objects.create(name='Albert', rebate='10%')
|
||||
self.assertEqual(Author.objects.get(), author)
|
||||
# Right-hand-side baked "%" literals should not be used for parameters
|
||||
# interpolation.
|
||||
check = ~models.Q(surname__startswith=models.F('name'))
|
||||
constraint = models.CheckConstraint(check=check, name='name_constraint_rhs')
|
||||
operation = migrations.AddConstraint('Author', constraint)
|
||||
from_state = to_state
|
||||
to_state = from_state.clone()
|
||||
operation.state_forwards(app_label, to_state)
|
||||
with connection.schema_editor() as editor:
|
||||
operation.database_forwards(app_label, editor, from_state, to_state)
|
||||
Author = to_state.apps.get_model(app_label, 'Author')
|
||||
with self.assertRaises(IntegrityError), transaction.atomic():
|
||||
Author.objects.create(name='Albert', surname='Alberto')
|
||||
|
||||
@skipUnlessDBFeature('supports_table_check_constraints')
|
||||
def test_add_or_constraint(self):
|
||||
|
|
Loading…
Reference in New Issue