diff options
author | Simon Charette <charette.s@gmail.com> | 2021-12-01 00:43:39 -0500 |
---|---|---|
committer | Mariusz Felisiak <felisiak.mariusz@gmail.com> | 2021-12-02 07:23:33 +0100 |
commit | e5a92d400acb4ca6a8e1375d1ab8121f2c7220be (patch) | |
tree | 288bbfaafb587ea31f752c0ea955d695e9edcd47 /tests/aggregation | |
parent | e3bde71676a704e27d62e5f96dd967f7305db7f2 (diff) | |
download | django-e5a92d400acb4ca6a8e1375d1ab8121f2c7220be.tar.gz |
Fixed #33282 -- Fixed a crash when OR'ing subquery and aggregation lookups.
As a QuerySet resolves to Query the outer column references grouping logic
should be defined on the latter and proxied from Subquery for the cases where
get_group_by_cols is called on unresolved expressions.
Thanks Antonio Terceiro for the report and initial patch.
Diffstat (limited to 'tests/aggregation')
-rw-r--r-- | tests/aggregation/tests.py | 34 |
1 files changed, 30 insertions, 4 deletions
diff --git a/tests/aggregation/tests.py b/tests/aggregation/tests.py index 72575a526c..87ae945a7e 100644 --- a/tests/aggregation/tests.py +++ b/tests/aggregation/tests.py @@ -1280,10 +1280,17 @@ class AggregateTestCase(TestCase): ).values( 'publisher' ).annotate(count=Count('pk')).values('count') - long_books_count_breakdown = Publisher.objects.values_list( - Subquery(long_books_count_qs, IntegerField()), - ).annotate(total=Count('*')) - self.assertEqual(dict(long_books_count_breakdown), {None: 1, 1: 4}) + groups = [ + Subquery(long_books_count_qs), + long_books_count_qs, + long_books_count_qs.query, + ] + for group in groups: + with self.subTest(group=group.__class__.__name__): + long_books_count_breakdown = Publisher.objects.values_list( + group, + ).annotate(total=Count('*')) + self.assertEqual(dict(long_books_count_breakdown), {None: 1, 1: 4}) @skipUnlessDBFeature('supports_subqueries_in_group_by') def test_group_by_exists_annotation(self): @@ -1341,6 +1348,25 @@ class AggregateTestCase(TestCase): ).values_list('publisher_count', flat=True) self.assertSequenceEqual(books_breakdown, [1] * 6) + def test_filter_in_subquery_or_aggregation(self): + """ + Filtering against an aggregate requires the usage of the HAVING clause. + + If such a filter is unionized to a non-aggregate one the latter will + also need to be moved to the HAVING clause and have its grouping + columns used in the GROUP BY. + + When this is done with a subquery the specialized logic in charge of + using outer reference columns to group should be used instead of the + subquery itself as the latter might return multiple rows. + """ + authors = Author.objects.annotate( + Count('book'), + ).filter( + Q(book__count__gt=0) | Q(pk__in=Book.objects.values('authors')) + ) + self.assertQuerysetEqual(authors, Author.objects.all(), ordered=False) + def test_aggregation_random_ordering(self): """Random() is not included in the GROUP BY when used for ordering.""" authors = Author.objects.annotate(contact_count=Count('book')).order_by('?') |