[1.8.x] Fixed #24752 -- query crash when reusing Case expressions

Case expressions weren't copied deep enough (self.cases list was
reused resulting in an error).

Backport of 7b05d2fdae from master
This commit is contained in:
Anssi Kääriäinen 2015-05-05 14:11:58 +03:00 committed by Tim Graham
parent eb00b427fc
commit 5b5858575c
3 changed files with 20 additions and 0 deletions

View File

@ -780,6 +780,11 @@ class Case(Expression):
c.default = c.default.resolve_expression(query, allow_joins, reuse, summarize, for_save) c.default = c.default.resolve_expression(query, allow_joins, reuse, summarize, for_save)
return c 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): def as_sql(self, compiler, connection, template=None, extra=None):
connection.ops.check_expression_support(self) connection.ops.check_expression_support(self)
if not self.cases: if not self.cases:

View File

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

View File

@ -274,6 +274,18 @@ class CaseExpressionTests(TestCase):
transform=attrgetter('integer', 'integer2') 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): def test_aggregate(self):
self.assertEqual( self.assertEqual(
CaseTestModel.objects.aggregate( CaseTestModel.objects.aggregate(