summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdam Johnson <me@adamj.eu>2025-05-21 13:48:59 +0100
committerSarah Boyce <42296566+sarahboyce@users.noreply.github.com>2025-05-23 16:15:59 +0200
commitc2615a050036eda0bca090c707191076220cee9f (patch)
treeaeeefc43af5b18d29b4073a16470af2cd7713ce0
parentb8e5a8a9a2a767f584cbe89a878a42363706f939 (diff)
Fixed #36405 -- Fixed Aggregate.order_by using OuterRef.
co-authored-by: Simon Charette <charette.s@gmail.com>
-rw-r--r--django/db/models/aggregates.py5
-rw-r--r--docs/releases/5.2.2.txt4
-rw-r--r--tests/aggregation/tests.py29
-rw-r--r--tests/postgres_tests/test_aggregates.py12
4 files changed, 45 insertions, 5 deletions
diff --git a/django/db/models/aggregates.py b/django/db/models/aggregates.py
index 6f1165014d..444d72addb 100644
--- a/django/db/models/aggregates.py
+++ b/django/db/models/aggregates.py
@@ -120,11 +120,6 @@ class Aggregate(Func):
):
# Aggregates are not allowed in UPDATE queries, so ignore for_save
c = super().resolve_expression(query, allow_joins, reuse, summarize)
- c.order_by = (
- c.order_by.resolve_expression(query, allow_joins, reuse, summarize)
- if c.order_by
- else None
- )
if summarize:
# Summarized aggregates cannot refer to summarized aggregates.
for ref in c.get_refs():
diff --git a/docs/releases/5.2.2.txt b/docs/releases/5.2.2.txt
index b8deb1c928..a506430b33 100644
--- a/docs/releases/5.2.2.txt
+++ b/docs/releases/5.2.2.txt
@@ -25,3 +25,7 @@ Bugfixes
* Fixed a regression in Django 5.2 that caused a crash when using ``OuterRef``
in the ``filter`` argument of an ``Aggregate`` expression (:ticket:`36404`).
+
+* Fixed a regression in Django 5.2 that caused a crash when using ``OuterRef``
+ in PostgreSQL aggregate functions ``ArrayAgg``, ``StringAgg``, and
+ ``JSONBAgg`` (:ticket:`36405`).
diff --git a/tests/aggregation/tests.py b/tests/aggregation/tests.py
index 6d284da63d..1cf3a8f66e 100644
--- a/tests/aggregation/tests.py
+++ b/tests/aggregation/tests.py
@@ -2413,6 +2413,35 @@ class AggregateTestCase(TestCase):
}
self.assertEqual(values, expected_values)
+ @skipUnlessDBFeature("supports_aggregate_order_by_clause")
+ def test_string_agg_filter_outerref(self):
+ values = (
+ Publisher.objects.annotate(
+ stringagg=Subquery(
+ Book.objects.annotate(
+ stringagg=StringAgg(
+ "name",
+ delimiter=Value(";"),
+ order_by=OuterRef("num_awards"),
+ )
+ ).values("stringagg")[:1]
+ )
+ )
+ .values("stringagg")
+ .order_by("id")
+ )
+
+ self.assertQuerySetEqual(
+ values,
+ [
+ {
+ "stringagg": "The Definitive Guide to Django: "
+ "Web Development Done Right"
+ }
+ ]
+ * 5,
+ )
+
@skipUnlessDBFeature("supports_json_field", "supports_aggregate_order_by_clause")
def test_string_agg_jsonfield_order_by(self):
Employee.objects.bulk_create(
diff --git a/tests/postgres_tests/test_aggregates.py b/tests/postgres_tests/test_aggregates.py
index ae386b6659..621fa43d91 100644
--- a/tests/postgres_tests/test_aggregates.py
+++ b/tests/postgres_tests/test_aggregates.py
@@ -364,6 +364,18 @@ class TestGeneralAggregate(PostgreSQLTestCase):
[[], [], [], []],
)
+ def test_array_agg_with_order_by_outer_ref(self):
+ StatTestModel.objects.annotate(
+ atm_ids=Subquery(
+ AggregateTestModel.objects.annotate(
+ ids=ArrayAgg(
+ "id",
+ order_by=[OuterRef("int1")],
+ )
+ ).values("ids")[:1]
+ )
+ )
+
def test_bit_and_general(self):
values = AggregateTestModel.objects.filter(integer_field__in=[0, 1]).aggregate(
bitand=BitAnd("integer_field")