[3.1.x] Refs #32096 -- Fixed crash of ArrayAgg/StringAgg/JSONBAgg with ordering over JSONField key transforms.

Regression in 6789ded0a6.

Thanks Igor Jerosimić for the report.

Backport of 1f31027bb3 from master
This commit is contained in:
Mariusz Felisiak 2020-10-12 13:02:12 +02:00
parent 735c88fdd7
commit d94e777b66
3 changed files with 28 additions and 2 deletions

View File

@ -24,7 +24,7 @@ class OrderableAggMixin:
ordering_params = [] ordering_params = []
ordering_expr_sql = [] ordering_expr_sql = []
for expr in self.ordering: for expr in self.ordering:
expr_sql, expr_params = expr.as_sql(compiler, connection) expr_sql, expr_params = compiler.compile(expr)
ordering_expr_sql.append(expr_sql) ordering_expr_sql.append(expr_sql)
ordering_params.extend(expr_params) ordering_params.extend(expr_params)
sql, sql_params = super().as_sql(compiler, connection, ordering=( sql, sql_params = super().as_sql(compiler, connection, ordering=(

View File

@ -20,3 +20,8 @@ Bugfixes
:class:`forms.JSONField <django.forms.JSONField>` and read-only :class:`forms.JSONField <django.forms.JSONField>` and read-only
:class:`models.JSONField <django.db.models.JSONField>` values in the admin :class:`models.JSONField <django.db.models.JSONField>` values in the admin
(:ticket:`32080`). (:ticket:`32080`).
* Fixed a regression in Django 3.1 that caused a crash of
:class:`~django.contrib.postgres.aggregates.ArrayAgg` and
:class:`~django.contrib.postgres.aggregates.StringAgg` with ``ordering``
on key transforms for :class:`~django.db.models.JSONField` (:ticket:`32096`).

View File

@ -1,7 +1,7 @@
import json import json
from django.db.models import CharField, F, OuterRef, Q, Subquery, Value from django.db.models import CharField, F, OuterRef, Q, Subquery, Value
from django.db.models.fields.json import KeyTransform from django.db.models.fields.json import KeyTextTransform, KeyTransform
from django.db.models.functions import Cast, Concat, Substr from django.db.models.functions import Cast, Concat, Substr
from django.test.utils import Approximate from django.test.utils import Approximate
@ -106,6 +106,16 @@ class TestGeneralAggregate(PostgreSQLTestCase):
) )
self.assertEqual(values, {'arrayagg': ['pl', 'en']}) self.assertEqual(values, {'arrayagg': ['pl', 'en']})
def test_array_agg_jsonfield_ordering(self):
values = AggregateTestModel.objects.aggregate(
arrayagg=ArrayAgg(
KeyTransform('lang', 'json_field'),
filter=Q(json_field__lang__isnull=False),
ordering=KeyTransform('lang', 'json_field'),
),
)
self.assertEqual(values, {'arrayagg': ['en', 'pl']})
def test_array_agg_filter(self): def test_array_agg_filter(self):
values = AggregateTestModel.objects.aggregate( values = AggregateTestModel.objects.aggregate(
arrayagg=ArrayAgg('integer_field', filter=Q(integer_field__gt=0)), arrayagg=ArrayAgg('integer_field', filter=Q(integer_field__gt=0)),
@ -220,6 +230,17 @@ class TestGeneralAggregate(PostgreSQLTestCase):
) )
self.assertEqual(values, {'stringagg': expected_output}) self.assertEqual(values, {'stringagg': expected_output})
def test_string_agg_jsonfield_ordering(self):
values = AggregateTestModel.objects.aggregate(
stringagg=StringAgg(
KeyTextTransform('lang', 'json_field'),
delimiter=';',
ordering=KeyTextTransform('lang', 'json_field'),
output_field=CharField(),
),
)
self.assertEqual(values, {'stringagg': 'en;pl'})
def test_string_agg_filter(self): def test_string_agg_filter(self):
values = AggregateTestModel.objects.aggregate( values = AggregateTestModel.objects.aggregate(
stringagg=StringAgg( stringagg=StringAgg(