Fixed #33895 -- Fixed Case() crash with filters that match everything in When().

Thanks shukryzablah for the report.
This commit is contained in:
David Wobrock 2022-08-07 17:25:43 +02:00 committed by Mariusz Felisiak
parent 63884829ac
commit 036bb2b74a
2 changed files with 15 additions and 0 deletions

View File

@ -1299,6 +1299,11 @@ class When(Expression):
template_params = extra_context template_params = extra_context
sql_params = [] sql_params = []
condition_sql, condition_params = compiler.compile(self.condition) condition_sql, condition_params = compiler.compile(self.condition)
# Filters that match everything are handled as empty strings in the
# WHERE clause, but in a CASE WHEN expression they must use a predicate
# that's always True.
if condition_sql == "":
condition_sql, condition_params = compiler.compile(Value(True))
template_params["condition"] = condition_sql template_params["condition"] = condition_sql
sql_params.extend(condition_params) sql_params.extend(condition_params)
result_sql, result_params = compiler.compile(self.result) result_sql, result_params = compiler.compile(self.result)

View File

@ -415,6 +415,16 @@ class CaseExpressionTests(TestCase):
self.assertEqual(len(objects), CaseTestModel.objects.count()) self.assertEqual(len(objects), CaseTestModel.objects.count())
self.assertTrue(all(obj.selected == "not selected" for obj in objects)) self.assertTrue(all(obj.selected == "not selected" for obj in objects))
def test_annotate_with_full_when(self):
objects = CaseTestModel.objects.annotate(
selected=Case(
When(~Q(pk__in=[]), then=Value("selected")),
default=Value("not selected"),
)
)
self.assertEqual(len(objects), CaseTestModel.objects.count())
self.assertTrue(all(obj.selected == "selected" for obj in objects))
def test_combined_expression(self): def test_combined_expression(self):
self.assertQuerysetEqual( self.assertQuerysetEqual(
CaseTestModel.objects.annotate( CaseTestModel.objects.annotate(