mirror of
				https://github.com/django/django.git
				synced 2025-10-31 01:25:32 +00:00 
			
		
		
		
	[2.2.x] Fixed #30412 -- Fixed crash when adding check constraints with OR'ed condition on Oracle and SQLite.
Backport of 719b746620 from master
			
			
This commit is contained in:
		| @@ -1309,7 +1309,7 @@ class Query: | |||||||
|             if isinstance(child, Node): |             if isinstance(child, Node): | ||||||
|                 child_clause, needed_inner = self._add_q( |                 child_clause, needed_inner = self._add_q( | ||||||
|                     child, used_aliases, branch_negated, |                     child, used_aliases, branch_negated, | ||||||
|                     current_negated, allow_joins, split_subq) |                     current_negated, allow_joins, split_subq, simple_col) | ||||||
|                 joinpromoter.add_votes(needed_inner) |                 joinpromoter.add_votes(needed_inner) | ||||||
|             else: |             else: | ||||||
|                 child_clause, needed_inner = self.build_filter( |                 child_clause, needed_inner = self.build_filter( | ||||||
|   | |||||||
| @@ -74,3 +74,6 @@ Bugfixes | |||||||
| * Fixed a migration crash on Oracle and PostgreSQL when adding a check | * Fixed a migration crash on Oracle and PostgreSQL when adding a check | ||||||
|   constraint with a ``contains``, ``startswith``, or ``endswith`` lookup (or |   constraint with a ``contains``, ``startswith``, or ``endswith`` lookup (or | ||||||
|   their case-insensitive variant) (:ticket:`30408`). |   their case-insensitive variant) (:ticket:`30408`). | ||||||
|  |  | ||||||
|  | * Fixed a migration crash on Oracle and SQLite when adding a check constraint | ||||||
|  |   with ``condition`` contains ``|`` (``OR``) operator (:ticket:`30412`). | ||||||
|   | |||||||
| @@ -1898,6 +1898,29 @@ class OperationTests(OperationTestBase): | |||||||
|         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) | ||||||
|  |  | ||||||
|  |     @skipUnlessDBFeature('supports_table_check_constraints') | ||||||
|  |     def test_add_or_constraint(self): | ||||||
|  |         app_label = 'test_addorconstraint' | ||||||
|  |         constraint_name = 'add_constraint_or' | ||||||
|  |         from_state = self.set_up_test_model(app_label) | ||||||
|  |         check = models.Q(pink__gt=2, weight__gt=2) | models.Q(weight__lt=0) | ||||||
|  |         constraint = models.CheckConstraint(check=check, name=constraint_name) | ||||||
|  |         operation = migrations.AddConstraint('Pony', 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) | ||||||
|  |         Pony = to_state.apps.get_model(app_label, 'Pony') | ||||||
|  |         with self.assertRaises(IntegrityError), transaction.atomic(): | ||||||
|  |             Pony.objects.create(pink=2, weight=3.0) | ||||||
|  |         with self.assertRaises(IntegrityError), transaction.atomic(): | ||||||
|  |             Pony.objects.create(pink=3, weight=1.0) | ||||||
|  |         Pony.objects.bulk_create([ | ||||||
|  |             Pony(pink=3, weight=-1.0), | ||||||
|  |             Pony(pink=1, weight=-1.0), | ||||||
|  |             Pony(pink=3, weight=3.0), | ||||||
|  |         ]) | ||||||
|  |  | ||||||
|     @skipUnlessDBFeature('supports_table_check_constraints') |     @skipUnlessDBFeature('supports_table_check_constraints') | ||||||
|     def test_remove_constraint(self): |     def test_remove_constraint(self): | ||||||
|         project_state = self.set_up_test_model("test_removeconstraint", constraints=[ |         project_state = self.set_up_test_model("test_removeconstraint", constraints=[ | ||||||
|   | |||||||
| @@ -23,6 +23,21 @@ class TestQuery(SimpleTestCase): | |||||||
|         self.assertEqual(lookup.rhs, 2) |         self.assertEqual(lookup.rhs, 2) | ||||||
|         self.assertEqual(lookup.lhs.target, Author._meta.get_field('num')) |         self.assertEqual(lookup.lhs.target, Author._meta.get_field('num')) | ||||||
|  |  | ||||||
|  |     def test_simplecol_query(self): | ||||||
|  |         query = Query(Author) | ||||||
|  |         where = query.build_where(Q(num__gt=2, name__isnull=False) | Q(num__lt=F('id'))) | ||||||
|  |  | ||||||
|  |         name_isnull_lookup, num_gt_lookup = where.children[0].children | ||||||
|  |         self.assertIsInstance(num_gt_lookup, GreaterThan) | ||||||
|  |         self.assertIsInstance(num_gt_lookup.lhs, SimpleCol) | ||||||
|  |         self.assertIsInstance(name_isnull_lookup, IsNull) | ||||||
|  |         self.assertIsInstance(name_isnull_lookup.lhs, SimpleCol) | ||||||
|  |  | ||||||
|  |         num_lt_lookup = where.children[1] | ||||||
|  |         self.assertIsInstance(num_lt_lookup, LessThan) | ||||||
|  |         self.assertIsInstance(num_lt_lookup.rhs, SimpleCol) | ||||||
|  |         self.assertIsInstance(num_lt_lookup.lhs, SimpleCol) | ||||||
|  |  | ||||||
|     def test_complex_query(self): |     def test_complex_query(self): | ||||||
|         query = Query(Author) |         query = Query(Author) | ||||||
|         where = query.build_where(Q(num__gt=2) | Q(num__lt=0)) |         where = query.build_where(Q(num__gt=2) | Q(num__lt=0)) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user