From 7b05d2fdaed582662d8f79130932f600f4f966a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anssi=20K=C3=A4=C3=A4ri=C3=A4inen?= Date: Tue, 5 May 2015 14:11:58 +0300 Subject: [PATCH] Fixed #24752 -- query crash when reusing Case expressions Case expressions weren't copied deep enough (self.cases list was reused resulting in an error). --- django/db/models/expressions.py | 5 +++++ docs/releases/1.8.2.txt | 3 +++ tests/expressions_case/tests.py | 12 ++++++++++++ 3 files changed, 20 insertions(+) diff --git a/django/db/models/expressions.py b/django/db/models/expressions.py index c6959f87b8..43061933e6 100644 --- a/django/db/models/expressions.py +++ b/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: diff --git a/docs/releases/1.8.2.txt b/docs/releases/1.8.2.txt index c66539c9b7..a0c18e78bb 100644 --- a/docs/releases/1.8.2.txt +++ b/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`). diff --git a/tests/expressions_case/tests.py b/tests/expressions_case/tests.py index 42fa8e61a4..2c3186f10e 100644 --- a/tests/expressions_case/tests.py +++ b/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(