1
0
mirror of https://github.com/django/django.git synced 2025-06-05 03:29:12 +00:00

Fixed #36405 -- Fixed Aggregate.order_by using OuterRef.

co-authored-by: Simon Charette <charette.s@gmail.com>
This commit is contained in:
Adam Johnson 2025-05-21 13:48:59 +01:00 committed by Sarah Boyce
parent b8e5a8a9a2
commit c2615a0500
4 changed files with 45 additions and 5 deletions

View File

@ -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():

View File

@ -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`).

View File

@ -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(

View File

@ -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")