Explorar el Código

Fixed #24752 -- query crash when reusing Case expressions

Case expressions weren't copied deep enough (self.cases list was
reused resulting in an error).
Anssi Kääriäinen hace 10 años
padre
commit
7b05d2fdae
Se han modificado 3 ficheros con 20 adiciones y 0 borrados
  1. 5 0
      django/db/models/expressions.py
  2. 3 0
      docs/releases/1.8.2.txt
  3. 12 0
      tests/expressions_case/tests.py

+ 5 - 0
django/db/models/expressions.py

@@ -780,6 +780,11 @@ class Case(Expression):
         c.default = c.default.resolve_expression(query, allow_joins, reuse, summarize, for_save)
         return c
 
+    def copy(self):
+        c = super(Case, self).copy()
+        c.cases = c.cases[:]
+        return c
+
     def as_sql(self, compiler, connection, template=None, extra=None):
         connection.ops.check_expression_support(self)
         if not self.cases:

+ 3 - 0
docs/releases/1.8.2.txt

@@ -10,3 +10,6 @@ Bugfixes
 ========
 
 * Fixed check for template engine alias uniqueness (:ticket:`24685`).
+
+* Fixed crash when reusing the same ``Case`` instance in a query
+  (:ticket:`24752`).

+ 12 - 0
tests/expressions_case/tests.py

@@ -274,6 +274,18 @@ class CaseExpressionTests(TestCase):
             transform=attrgetter('integer', 'integer2')
         )
 
+    def test_case_reuse(self):
+        SOME_CASE = Case(
+            When(pk=0, then=Value('0')),
+            default=Value('1'),
+            output_field=models.CharField(),
+        )
+        self.assertQuerysetEqual(
+            CaseTestModel.objects.annotate(somecase=SOME_CASE).order_by('pk'),
+            CaseTestModel.objects.annotate(somecase=SOME_CASE).order_by('pk').values_list('pk', 'somecase'),
+            lambda x: (x.pk, x.somecase)
+        )
+
     def test_aggregate(self):
         self.assertEqual(
             CaseTestModel.objects.aggregate(