mirror of
				https://github.com/django/django.git
				synced 2025-10-31 01:25:32 +00:00 
			
		
		
		
	[3.2.x] 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.
Backport of 42e8cf47c7 from master
			
			
This commit is contained in:
		
				
					committed by
					
						 Mariusz Felisiak
						Mariusz Felisiak
					
				
			
			
				
	
			
			
			
						parent
						
							5d9374b9fb
						
					
				
				
					commit
					9607e3a0cc
				
			| @@ -360,6 +360,8 @@ class BaseDatabaseSchemaEditor: | |||||||
|             not self.connection.features.supports_expression_indexes |             not self.connection.features.supports_expression_indexes | ||||||
|         ): |         ): | ||||||
|             return None |             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) |         self.execute(index.create_sql(model, self), params=None) | ||||||
|  |  | ||||||
|     def remove_index(self, model, index): |     def remove_index(self, model, index): | ||||||
| @@ -375,7 +377,9 @@ class BaseDatabaseSchemaEditor: | |||||||
|         """Add a constraint to a model.""" |         """Add a constraint to a model.""" | ||||||
|         sql = constraint.create_sql(model, self) |         sql = constraint.create_sql(model, self) | ||||||
|         if sql: |         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): |     def remove_constraint(self, model, constraint): | ||||||
|         """Remove a constraint from a model.""" |         """Remove a constraint from a model.""" | ||||||
|   | |||||||
| @@ -2145,6 +2145,7 @@ class OperationTests(OperationTestBase): | |||||||
|                 fields=[ |                 fields=[ | ||||||
|                     ('id', models.AutoField(primary_key=True)), |                     ('id', models.AutoField(primary_key=True)), | ||||||
|                     ('name', models.CharField(max_length=100)), |                     ('name', models.CharField(max_length=100)), | ||||||
|  |                     ('surname', models.CharField(max_length=100, default='')), | ||||||
|                     ('rebate', models.CharField(max_length=100)), |                     ('rebate', models.CharField(max_length=100)), | ||||||
|                 ], |                 ], | ||||||
|             ), |             ), | ||||||
| @@ -2178,6 +2179,19 @@ class OperationTests(OperationTestBase): | |||||||
|             Author.objects.create(name='Albert', rebate='10$') |             Author.objects.create(name='Albert', rebate='10$') | ||||||
|         author = Author.objects.create(name='Albert', rebate='10%') |         author = Author.objects.create(name='Albert', rebate='10%') | ||||||
|         self.assertEqual(Author.objects.get(), author) |         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') |     @skipUnlessDBFeature('supports_table_check_constraints') | ||||||
|     def test_add_or_constraint(self): |     def test_add_or_constraint(self): | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user