Refs #10929 -- Deprecated forced empty result value for PostgreSQL aggregates.

This deprecates forcing a return value for ArrayAgg, JSONBAgg, and
StringAgg when there are no rows in the query. Now that we have a
``default`` argument for aggregates, we want to revert to returning the
default of ``None`` which most aggregate functions return and leave it
up to the user to decide what they want to be returned by default.
This commit is contained in:
Nick Pope 2021-06-30 00:08:27 +01:00 committed by Mariusz Felisiak
parent 501a8db465
commit fee8734596
5 changed files with 130 additions and 18 deletions

View file

@ -3,7 +3,8 @@ from django.db.models import (
)
from django.db.models.fields.json import KeyTextTransform, KeyTransform
from django.db.models.functions import Cast, Concat, Substr
from django.test.utils import Approximate
from django.test.utils import Approximate, ignore_warnings
from django.utils.deprecation import RemovedInDjango50Warning
from . import PostgreSQLTestCase
from .models import AggregateTestModel, StatTestModel
@ -44,6 +45,7 @@ class TestGeneralAggregate(PostgreSQLTestCase):
),
])
@ignore_warnings(category=RemovedInDjango50Warning)
def test_empty_result_set(self):
AggregateTestModel.objects.all().delete()
tests = [
@ -100,6 +102,49 @@ class TestGeneralAggregate(PostgreSQLTestCase):
)
self.assertEqual(values, {'aggregation': expected_result})
def test_convert_value_deprecation(self):
AggregateTestModel.objects.all().delete()
queryset = AggregateTestModel.objects.all()
with self.assertWarnsMessage(RemovedInDjango50Warning, ArrayAgg.deprecation_msg):
queryset.aggregate(aggregation=ArrayAgg('boolean_field'))
with self.assertWarnsMessage(RemovedInDjango50Warning, JSONBAgg.deprecation_msg):
queryset.aggregate(aggregation=JSONBAgg('integer_field'))
with self.assertWarnsMessage(RemovedInDjango50Warning, StringAgg.deprecation_msg):
queryset.aggregate(aggregation=StringAgg('char_field', delimiter=';'))
# No warnings raised if default argument provided.
self.assertEqual(
queryset.aggregate(aggregation=ArrayAgg('boolean_field', default=None)),
{'aggregation': None},
)
self.assertEqual(
queryset.aggregate(aggregation=JSONBAgg('integer_field', default=None)),
{'aggregation': None},
)
self.assertEqual(
queryset.aggregate(
aggregation=StringAgg('char_field', delimiter=';', default=None),
),
{'aggregation': None},
)
self.assertEqual(
queryset.aggregate(aggregation=ArrayAgg('boolean_field', default=Value([]))),
{'aggregation': []},
)
self.assertEqual(
queryset.aggregate(aggregation=JSONBAgg('integer_field', default=Value('[]'))),
{'aggregation': []},
)
self.assertEqual(
queryset.aggregate(
aggregation=StringAgg('char_field', delimiter=';', default=Value('')),
),
{'aggregation': ''},
)
def test_array_agg_charfield(self):
values = AggregateTestModel.objects.aggregate(arrayagg=ArrayAgg('char_field'))
self.assertEqual(values, {'arrayagg': ['Foo1', 'Foo2', 'Foo4', 'Foo3']})