mirror of
https://github.com/django/django.git
synced 2025-08-04 02:48:35 +00:00
Fixed #30408 -- Fixed crash when adding check constraints with LIKE operator on Oracle and PostgreSQL.
The LIKE operator wildcard generated for contains, startswith, endswith and their case-insensitive variant lookups was conflicting with parameter interpolation on CREATE constraint statement execution. Ideally we'd delegate parameters interpolation in DDL statements on backends that support it but that would require backward incompatible changes to the Index and Constraint SQL generating methods. Thanks David Sanders for the report.
This commit is contained in:
parent
673fe2e3ec
commit
a8b3f96f6a
4 changed files with 50 additions and 1 deletions
|
@ -1855,6 +1855,49 @@ class OperationTests(OperationTestBase):
|
|||
self.assertEqual(definition[1], [])
|
||||
self.assertEqual(definition[2], {'model_name': "Pony", 'constraint': gt_constraint})
|
||||
|
||||
@skipUnlessDBFeature('supports_table_check_constraints')
|
||||
def test_add_constraint_percent_escaping(self):
|
||||
app_label = 'add_constraint_string_quoting'
|
||||
operations = [
|
||||
CreateModel(
|
||||
'Author',
|
||||
fields=[
|
||||
('id', models.AutoField(primary_key=True)),
|
||||
('name', models.CharField(max_length=100)),
|
||||
('rebate', models.CharField(max_length=100)),
|
||||
],
|
||||
),
|
||||
]
|
||||
from_state = self.apply_operations(app_label, ProjectState(), operations)
|
||||
# "%" generated in startswith lookup should be escaped in a way that is
|
||||
# considered a leading wildcard.
|
||||
check = models.Q(name__startswith='Albert')
|
||||
constraint = models.CheckConstraint(check=check, name='name_constraint')
|
||||
operation = migrations.AddConstraint('Author', constraint)
|
||||
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='Artur')
|
||||
# Literal "%" should be escaped in a way that is not a considered a
|
||||
# wildcard.
|
||||
check = models.Q(rebate__endswith='%')
|
||||
constraint = models.CheckConstraint(check=check, name='rebate_constraint')
|
||||
operation = migrations.AddConstraint('Author', constraint)
|
||||
from_state = to_state
|
||||
to_state = from_state.clone()
|
||||
operation.state_forwards(app_label, to_state)
|
||||
Author = to_state.apps.get_model(app_label, 'Author')
|
||||
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', rebate='10$')
|
||||
author = Author.objects.create(name='Albert', rebate='10%')
|
||||
self.assertEqual(Author.objects.get(), author)
|
||||
|
||||
@skipUnlessDBFeature('supports_table_check_constraints')
|
||||
def test_remove_constraint(self):
|
||||
project_state = self.set_up_test_model("test_removeconstraint", constraints=[
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue