1
0
mirror of https://github.com/django/django.git synced 2025-06-17 17:39:16 +00:00

Fixed #36407 -- Ensured default value is cast in Case expressions used in ORDER BY clause.

Thanks to deceze for the report. Thanks to Sarah Boyce for the test.
Thanks to Simon Charette for the investigation and review.
This commit is contained in:
ontowhee 2025-05-22 11:06:28 -07:00 committed by Sarah Boyce
parent 51923c576a
commit 68c9f7e0b7
2 changed files with 28 additions and 4 deletions

View File

@ -1711,14 +1711,24 @@ class Case(SQLiteNumericMixin, Expression):
except EmptyResultSet: except EmptyResultSet:
continue continue
except FullResultSet: except FullResultSet:
default_sql, default_params = compiler.compile(case.result) default = case.result
break break
case_parts.append(case_sql) case_parts.append(case_sql)
sql_params.extend(case_params) sql_params.extend(case_params)
else: else:
default_sql, default_params = compiler.compile(self.default) default = self.default
if not case_parts: if case_parts:
return default_sql, default_params default_sql, default_params = compiler.compile(default)
else:
if (
isinstance(default, Value)
and (output_field := default._output_field_or_none) is not None
):
from django.db.models.functions import Cast
default = Cast(default, output_field)
return compiler.compile(default)
case_joiner = case_joiner or self.case_joiner case_joiner = case_joiner or self.case_joiner
template_params["cases"] = case_joiner.join(case_parts) template_params["cases"] = case_joiner.join(case_parts)
template_params["default"] = default_sql template_params["default"] = default_sql

View File

@ -3,15 +3,18 @@ from operator import attrgetter
from django.core.exceptions import FieldError from django.core.exceptions import FieldError
from django.db.models import ( from django.db.models import (
Case,
CharField, CharField,
Count, Count,
DateTimeField, DateTimeField,
F, F,
IntegerField,
Max, Max,
OrderBy, OrderBy,
OuterRef, OuterRef,
Subquery, Subquery,
Value, Value,
When,
) )
from django.db.models.functions import Length, Upper from django.db.models.functions import Length, Upper
from django.test import TestCase from django.test import TestCase
@ -526,6 +529,17 @@ class OrderingTests(TestCase):
qs = Article.objects.order_by(Value("1", output_field=CharField()), "-headline") qs = Article.objects.order_by(Value("1", output_field=CharField()), "-headline")
self.assertSequenceEqual(qs, [self.a4, self.a3, self.a2, self.a1]) self.assertSequenceEqual(qs, [self.a4, self.a3, self.a2, self.a1])
def test_order_by_case_when_constant_value(self):
qs = Article.objects.order_by(
Case(
When(pk__in=[], then=Value(1)),
default=Value(0),
output_field=IntegerField(),
).desc(),
"pk",
)
self.assertSequenceEqual(qs, [self.a1, self.a2, self.a3, self.a4])
def test_related_ordering_duplicate_table_reference(self): def test_related_ordering_duplicate_table_reference(self):
""" """
An ordering referencing a model with an ordering referencing a model An ordering referencing a model with an ordering referencing a model