Fixed #11881 -- removed junk from aggregation subqueries
There were clauses that weren't needed in the subqueries. These were ORDER BY, SELECT FOR UPDATE and related selections.
This commit is contained in:
parent
7737305a4f
commit
7bc57a6d71
|
@ -330,8 +330,16 @@ class Query(object):
|
||||||
from django.db.models.sql.subqueries import AggregateQuery
|
from django.db.models.sql.subqueries import AggregateQuery
|
||||||
query = AggregateQuery(self.model)
|
query = AggregateQuery(self.model)
|
||||||
obj = self.clone()
|
obj = self.clone()
|
||||||
relabels = dict((t, 'subquery') for t in self.tables)
|
if not force_subq:
|
||||||
|
# In forced subq case the ordering and limits will likely
|
||||||
|
# affect the results.
|
||||||
|
obj.clear_ordering(True)
|
||||||
|
obj.clear_limits()
|
||||||
|
obj.select_for_update = False
|
||||||
|
obj.select_related = False
|
||||||
|
obj.related_select_cols = []
|
||||||
|
|
||||||
|
relabels = dict((t, 'subquery') for t in self.tables)
|
||||||
# Remove any aggregates marked for reduction from the subquery
|
# Remove any aggregates marked for reduction from the subquery
|
||||||
# and move them to the outer AggregateQuery.
|
# and move them to the outer AggregateQuery.
|
||||||
for alias, aggregate in self.aggregate_select.items():
|
for alias, aggregate in self.aggregate_select.items():
|
||||||
|
|
|
@ -3,8 +3,10 @@ from __future__ import unicode_literals
|
||||||
import datetime
|
import datetime
|
||||||
from decimal import Decimal
|
from decimal import Decimal
|
||||||
|
|
||||||
|
from django.db import connection
|
||||||
from django.db.models import Avg, Sum, Count, Max, Min
|
from django.db.models import Avg, Sum, Count, Max, Min
|
||||||
from django.test import TestCase, Approximate
|
from django.test import TestCase, Approximate
|
||||||
|
from django.test.utils import CaptureQueriesContext
|
||||||
|
|
||||||
from .models import Author, Publisher, Book, Store
|
from .models import Author, Publisher, Book, Store
|
||||||
|
|
||||||
|
@ -625,3 +627,18 @@ class BaseAggregateTestCase(TestCase):
|
||||||
qs = Book.objects.all().order_by('-rating')[0:3]
|
qs = Book.objects.all().order_by('-rating')[0:3]
|
||||||
vals = qs.aggregate(average_top3_rating=Avg('rating'))['average_top3_rating']
|
vals = qs.aggregate(average_top3_rating=Avg('rating'))['average_top3_rating']
|
||||||
self.assertAlmostEqual(vals, 4.5, places=2)
|
self.assertAlmostEqual(vals, 4.5, places=2)
|
||||||
|
|
||||||
|
def test_ticket11881(self):
|
||||||
|
"""
|
||||||
|
Check that subqueries do not needlessly contain ORDER BY, SELECT FOR UPDATE
|
||||||
|
or select_related() stuff.
|
||||||
|
"""
|
||||||
|
qs = Book.objects.all().select_for_update().order_by(
|
||||||
|
'pk').select_related('publisher').annotate(max_pk=Max('pk'))
|
||||||
|
with CaptureQueriesContext(connection) as captured_queries:
|
||||||
|
qs.aggregate(avg_pk=Avg('max_pk'))
|
||||||
|
self.assertEqual(len(captured_queries), 1)
|
||||||
|
qstr = captured_queries[0]['sql'].lower()
|
||||||
|
self.assertNotIn('for update', qstr)
|
||||||
|
self.assertNotIn('order by', qstr)
|
||||||
|
self.assertEqual(qstr.count(' join '), 0)
|
||||||
|
|
Loading…
Reference in New Issue