Fixed #31097 -- Fixed crash of ArrayAgg and StringAgg with filter when used in Subquery.

This commit is contained in:
David Wobrock 2019-12-28 22:42:46 +01:00 committed by Mariusz Felisiak
parent 7d44aeb388
commit 2f565f84ac
3 changed files with 47 additions and 11 deletions

View file

@ -21,7 +21,7 @@ except ImportError:
class TestGeneralAggregate(PostgreSQLTestCase):
@classmethod
def setUpTestData(cls):
AggregateTestModel.objects.create(boolean_field=True, char_field='Foo1', integer_field=0)
cls.agg1 = AggregateTestModel.objects.create(boolean_field=True, char_field='Foo1', integer_field=0)
AggregateTestModel.objects.create(boolean_field=False, char_field='Foo2', integer_field=1)
AggregateTestModel.objects.create(boolean_field=False, char_field='Foo4', integer_field=2)
AggregateTestModel.objects.create(boolean_field=True, char_field='Foo3', integer_field=0)
@ -249,6 +249,50 @@ class TestGeneralAggregate(PostgreSQLTestCase):
).order_by('char_field').values_list('char_field', 'agg')
self.assertEqual(list(values), expected_result)
def test_string_agg_array_agg_filter_in_subquery(self):
StatTestModel.objects.bulk_create([
StatTestModel(related_field=self.agg1, int1=0, int2=5),
StatTestModel(related_field=self.agg1, int1=1, int2=4),
StatTestModel(related_field=self.agg1, int1=2, int2=3),
])
for aggregate, expected_result in (
(
ArrayAgg('stattestmodel__int1', filter=Q(stattestmodel__int2__gt=3)),
[('Foo1', [0, 1]), ('Foo2', None)],
),
(
StringAgg(
Cast('stattestmodel__int2', CharField()),
delimiter=';',
filter=Q(stattestmodel__int1__lt=2),
),
[('Foo1', '5;4'), ('Foo2', None)],
),
):
with self.subTest(aggregate=aggregate.__class__.__name__):
subquery = AggregateTestModel.objects.filter(
pk=OuterRef('pk'),
).annotate(agg=aggregate).values('agg')
values = AggregateTestModel.objects.annotate(
agg=Subquery(subquery),
).filter(
char_field__in=['Foo1', 'Foo2'],
).order_by('char_field').values_list('char_field', 'agg')
self.assertEqual(list(values), expected_result)
def test_string_agg_filter_in_subquery_with_exclude(self):
subquery = AggregateTestModel.objects.annotate(
stringagg=StringAgg(
'char_field',
delimiter=';',
filter=Q(char_field__endswith='1'),
)
).exclude(stringagg='').values('id')
self.assertSequenceEqual(
AggregateTestModel.objects.filter(id__in=Subquery(subquery)),
[self.agg1],
)
class TestAggregateDistinct(PostgreSQLTestCase):
@classmethod