Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

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.
  • Loading branch information...
commit 7bc57a6d71dd4d00bb09cfa67be547591fd759ce 1 parent 7737305
@akaariai akaariai authored
Showing with 26 additions and 1 deletion.
  1. +9 −1 django/db/models/sql/query.py
  2. +17 −0 tests/aggregation/tests.py
View
10 django/db/models/sql/query.py
@@ -330,8 +330,16 @@ def get_aggregation(self, using, force_subq=False):
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():
View
17 tests/aggregation/tests.py
@@ -3,8 +3,10 @@
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
@@ -625,3 +627,18 @@ def test_ticket12886(self):
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)
Please sign in to comment.
Something went wrong with that request. Please try again.