summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Charette <charette.s@gmail.com>2023-12-29 01:03:54 -0500
committerMariusz Felisiak <felisiak.mariusz@gmail.com>2023-12-29 09:07:31 +0100
commite16d0c176e9b89628cdec5e58c418378c4a2436a (patch)
tree8cb49f6b106ef7a750a31ce572beb95eb86eb516
parent90d365d869924d503565eb1ccdc24077d60faf0c (diff)
Fixed #35064 -- Fixed Window(order_by) crash with DecimalFields on SQLite.
This avoids cast of Window(order_by) for DecimalFields on SQLite. This was achieved by piggy-backing ExpressionList which already implements a specialized as_sqlite() method to override the inherited behaviour of Func through SQLiteNumericMixin. Refs #31723. Thanks Quoates for the report.
-rw-r--r--django/db/models/expressions.py17
-rw-r--r--tests/expressions_window/tests.py26
2 files changed, 27 insertions, 16 deletions
diff --git a/django/db/models/expressions.py b/django/db/models/expressions.py
index 41443dc6db..b67a2418d4 100644
--- a/django/db/models/expressions.py
+++ b/django/db/models/expressions.py
@@ -1267,12 +1267,12 @@ class ExpressionList(Func):
def get_group_by_cols(self):
group_by_cols = []
- for partition in self.get_source_expressions():
- group_by_cols.extend(partition.get_group_by_cols())
+ for expr in self.get_source_expressions():
+ group_by_cols.extend(expr.get_group_by_cols())
return group_by_cols
-class OrderByList(Func):
+class OrderByList(ExpressionList):
allowed_default = False
template = "ORDER BY %(expressions)s"
@@ -1287,17 +1287,6 @@ class OrderByList(Func):
)
super().__init__(*expressions, **extra)
- def as_sql(self, *args, **kwargs):
- if not self.source_expressions:
- return "", ()
- return super().as_sql(*args, **kwargs)
-
- def get_group_by_cols(self):
- group_by_cols = []
- for order_by in self.get_source_expressions():
- group_by_cols.extend(order_by.get_group_by_cols())
- return group_by_cols
-
@deconstructible(path="django.db.models.ExpressionWrapper")
class ExpressionWrapper(SQLiteNumericMixin, Expression):
diff --git a/tests/expressions_window/tests.py b/tests/expressions_window/tests.py
index fb14e56349..fd674e319b 100644
--- a/tests/expressions_window/tests.py
+++ b/tests/expressions_window/tests.py
@@ -354,6 +354,29 @@ class WindowFunctionTests(TestCase):
transform=lambda row: (row.name, row.bonus, row.department, row.lag),
)
+ def test_order_by_decimalfield(self):
+ qs = Employee.objects.annotate(
+ rank=Window(expression=Rank(), order_by="bonus")
+ ).order_by("-bonus", "id")
+ self.assertQuerySetEqual(
+ qs,
+ [
+ ("Miller", 250.0, 12),
+ ("Johnson", 200.0, 11),
+ ("Wilkinson", 150.0, 10),
+ ("Smith", 137.5, 9),
+ ("Brown", 132.5, 8),
+ ("Adams", 125.0, 7),
+ ("Jones", 112.5, 5),
+ ("Jenson", 112.5, 5),
+ ("Johnson", 100.0, 4),
+ ("Smith", 95.0, 3),
+ ("Williams", 92.5, 2),
+ ("Moore", 85.0, 1),
+ ],
+ transform=lambda row: (row.name, float(row.bonus), row.rank),
+ )
+
def test_first_value(self):
qs = Employee.objects.annotate(
first_value=Window(
@@ -1934,8 +1957,7 @@ class NonQueryWindowTests(SimpleTestCase):
)
self.assertEqual(
repr(Window(expression=Avg("salary"), order_by=F("department").asc())),
- "<Window: Avg(F(salary)) OVER (OrderByList(OrderBy(F(department), "
- "descending=False)))>",
+ "<Window: Avg(F(salary)) OVER (OrderBy(F(department), descending=False))>",
)
def test_window_frame_repr(self):