Loading django/db/models/sql/query.py +9 −1 Original line number Diff line number Diff line Loading @@ -330,8 +330,16 @@ class Query(object): from django.db.models.sql.subqueries import AggregateQuery query = AggregateQuery(self.model) 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 # and move them to the outer AggregateQuery. for alias, aggregate in self.aggregate_select.items(): Loading tests/aggregation/tests.py +17 −0 Original line number Diff line number Diff line Loading @@ -3,8 +3,10 @@ from __future__ import unicode_literals import datetime from decimal import Decimal from django.db import connection from django.db.models import Avg, Sum, Count, Max, Min from django.test import TestCase, Approximate from django.test.utils import CaptureQueriesContext from .models import Author, Publisher, Book, Store Loading Loading @@ -625,3 +627,18 @@ class BaseAggregateTestCase(TestCase): qs = Book.objects.all().order_by('-rating')[0:3] vals = qs.aggregate(average_top3_rating=Avg('rating'))['average_top3_rating'] 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
django/db/models/sql/query.py +9 −1 Original line number Diff line number Diff line Loading @@ -330,8 +330,16 @@ class Query(object): from django.db.models.sql.subqueries import AggregateQuery query = AggregateQuery(self.model) 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 # and move them to the outer AggregateQuery. for alias, aggregate in self.aggregate_select.items(): Loading
tests/aggregation/tests.py +17 −0 Original line number Diff line number Diff line Loading @@ -3,8 +3,10 @@ from __future__ import unicode_literals import datetime from decimal import Decimal from django.db import connection from django.db.models import Avg, Sum, Count, Max, Min from django.test import TestCase, Approximate from django.test.utils import CaptureQueriesContext from .models import Author, Publisher, Book, Store Loading Loading @@ -625,3 +627,18 @@ class BaseAggregateTestCase(TestCase): qs = Book.objects.all().order_by('-rating')[0:3] vals = qs.aggregate(average_top3_rating=Avg('rating'))['average_top3_rating'] 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)