[3.1.x] Refs #32096 -- Added test for ArrayAgg over JSONField key transforms.

Backport of 1d650ad019 from master
This commit is contained in:
Mariusz Felisiak 2020-10-12 12:52:58 +02:00
parent 84685e5132
commit 735c88fdd7
3 changed files with 47 additions and 12 deletions

View File

@ -202,7 +202,11 @@ class Migration(migrations.Migration):
('boolean_field', models.BooleanField(null=True)), ('boolean_field', models.BooleanField(null=True)),
('char_field', models.CharField(max_length=30, blank=True)), ('char_field', models.CharField(max_length=30, blank=True)),
('integer_field', models.IntegerField(null=True)), ('integer_field', models.IntegerField(null=True)),
] ('json_field', models.JSONField(null=True)),
],
options={
'required_db_vendor': 'postgresql',
},
), ),
migrations.CreateModel( migrations.CreateModel(
name='StatTestModel', name='StatTestModel',
@ -215,7 +219,10 @@ class Migration(migrations.Migration):
models.SET_NULL, models.SET_NULL,
null=True, null=True,
)), )),
] ],
options={
'required_db_vendor': 'postgresql',
},
), ),
migrations.CreateModel( migrations.CreateModel(
name='NowTestModel', name='NowTestModel',

View File

@ -154,16 +154,17 @@ class ArrayFieldSubclass(ArrayField):
super().__init__(models.IntegerField()) super().__init__(models.IntegerField())
class AggregateTestModel(models.Model): class AggregateTestModel(PostgreSQLModel):
""" """
To test postgres-specific general aggregation functions To test postgres-specific general aggregation functions
""" """
char_field = models.CharField(max_length=30, blank=True) char_field = models.CharField(max_length=30, blank=True)
integer_field = models.IntegerField(null=True) integer_field = models.IntegerField(null=True)
boolean_field = models.BooleanField(null=True) boolean_field = models.BooleanField(null=True)
json_field = models.JSONField(null=True)
class StatTestModel(models.Model): class StatTestModel(PostgreSQLModel):
""" """
To test postgres-specific aggregation functions for statistics To test postgres-specific aggregation functions for statistics
""" """

View File

@ -1,6 +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.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
@ -20,10 +21,27 @@ except ImportError:
class TestGeneralAggregate(PostgreSQLTestCase): class TestGeneralAggregate(PostgreSQLTestCase):
@classmethod @classmethod
def setUpTestData(cls): def setUpTestData(cls):
cls.agg1 = AggregateTestModel.objects.create(boolean_field=True, char_field='Foo1', integer_field=0) cls.aggs = AggregateTestModel.objects.bulk_create([
AggregateTestModel.objects.create(boolean_field=False, char_field='Foo2', integer_field=1) AggregateTestModel(boolean_field=True, char_field='Foo1', integer_field=0),
AggregateTestModel.objects.create(boolean_field=False, char_field='Foo4', integer_field=2) AggregateTestModel(
AggregateTestModel.objects.create(boolean_field=True, char_field='Foo3', integer_field=0) boolean_field=False,
char_field='Foo2',
integer_field=1,
json_field={'lang': 'pl'},
),
AggregateTestModel(
boolean_field=False,
char_field='Foo4',
integer_field=2,
json_field={'lang': 'en'},
),
AggregateTestModel(
boolean_field=True,
char_field='Foo3',
integer_field=0,
json_field={'breed': 'collie'},
),
])
def test_array_agg_charfield(self): def test_array_agg_charfield(self):
values = AggregateTestModel.objects.aggregate(arrayagg=ArrayAgg('char_field')) values = AggregateTestModel.objects.aggregate(arrayagg=ArrayAgg('char_field'))
@ -79,6 +97,15 @@ class TestGeneralAggregate(PostgreSQLTestCase):
) )
self.assertEqual(values, {'arrayagg': expected_output}) self.assertEqual(values, {'arrayagg': expected_output})
def test_array_agg_jsonfield(self):
values = AggregateTestModel.objects.aggregate(
arrayagg=ArrayAgg(
KeyTransform('lang', 'json_field'),
filter=Q(json_field__lang__isnull=False),
),
)
self.assertEqual(values, {'arrayagg': ['pl', 'en']})
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)),
@ -254,9 +281,9 @@ class TestGeneralAggregate(PostgreSQLTestCase):
def test_string_agg_array_agg_filter_in_subquery(self): def test_string_agg_array_agg_filter_in_subquery(self):
StatTestModel.objects.bulk_create([ StatTestModel.objects.bulk_create([
StatTestModel(related_field=self.agg1, int1=0, int2=5), StatTestModel(related_field=self.aggs[0], int1=0, int2=5),
StatTestModel(related_field=self.agg1, int1=1, int2=4), StatTestModel(related_field=self.aggs[0], int1=1, int2=4),
StatTestModel(related_field=self.agg1, int1=2, int2=3), StatTestModel(related_field=self.aggs[0], int1=2, int2=3),
]) ])
for aggregate, expected_result in ( for aggregate, expected_result in (
( (
@ -293,7 +320,7 @@ class TestGeneralAggregate(PostgreSQLTestCase):
).exclude(stringagg='').values('id') ).exclude(stringagg='').values('id')
self.assertSequenceEqual( self.assertSequenceEqual(
AggregateTestModel.objects.filter(id__in=Subquery(subquery)), AggregateTestModel.objects.filter(id__in=Subquery(subquery)),
[self.agg1], [self.aggs[0]],
) )