If an SQL query doesn't specify any ordering, avoid the implicit sort
that happens with MySQL when a "GROUP BY" clause is included. This is a backend-specific operation, so any other databases requiring similar encouragement can have a function added to their own backend code. git-svn-id: http://code.djangoproject.com/svn/django/trunk@9637 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
7030ab9a72
commit
a1cbeb9afb
|
@ -143,6 +143,14 @@ class BaseDatabaseOperations(object):
|
|||
"""
|
||||
return '%s'
|
||||
|
||||
def force_no_ordering(self):
|
||||
"""
|
||||
Returns a list used in the "ORDER BY" clause to force no ordering at
|
||||
all. Returning an empty list means that nothing will be included in the
|
||||
ordering.
|
||||
"""
|
||||
return []
|
||||
|
||||
def fulltext_search_sql(self, field_name):
|
||||
"""
|
||||
Returns the SQL WHERE clause to use in order to perform a full-text
|
||||
|
|
|
@ -133,6 +133,14 @@ class DatabaseOperations(BaseDatabaseOperations):
|
|||
def drop_foreignkey_sql(self):
|
||||
return "DROP FOREIGN KEY"
|
||||
|
||||
def force_no_ordering(self):
|
||||
"""
|
||||
"ORDER BY NULL" prevents MySQL from implicitly ordering by grouped
|
||||
columns. If no ordering would otherwise be applied, we don't want any
|
||||
implicit sorting going on.
|
||||
"""
|
||||
return ["NULL"]
|
||||
|
||||
def fulltext_search_sql(self, field_name):
|
||||
return 'MATCH (%s) AGAINST (%%s IN BOOLEAN MODE)' % field_name
|
||||
|
||||
|
|
|
@ -288,6 +288,8 @@ class BaseQuery(object):
|
|||
if self.group_by:
|
||||
grouping = self.get_grouping()
|
||||
result.append('GROUP BY %s' % ', '.join(grouping))
|
||||
if not ordering:
|
||||
ordering = self.connection.ops.force_no_ordering()
|
||||
|
||||
if self.having:
|
||||
having, h_params = self.get_having()
|
||||
|
|
|
@ -6,6 +6,7 @@ import datetime
|
|||
import pickle
|
||||
import sys
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import models
|
||||
from django.db.models.query import Q, ITER_CHUNK_SIZE
|
||||
|
||||
|
@ -1053,3 +1054,20 @@ FieldError: Infinite loop caused by ordering.
|
|||
[]
|
||||
|
||||
"""
|
||||
|
||||
if settings.DATABASE_ENGINE == "mysql":
|
||||
__test__["API_TESTS"] += """
|
||||
When grouping without specifying ordering, we add an explicit "ORDER BY NULL"
|
||||
portion in MySQL to prevent unnecessary sorting.
|
||||
|
||||
>>> query = Tag.objects.values_list('parent_id', flat=True).order_by().query
|
||||
>>> query.group_by = ['parent_id']
|
||||
>>> sql = query.as_sql()[0]
|
||||
>>> fragment = "ORDER BY "
|
||||
>>> pos = sql.find(fragment)
|
||||
>>> sql.find(fragment, pos + 1) == -1
|
||||
True
|
||||
>>> sql.find("NULL", pos + len(fragment)) == pos + len(fragment)
|
||||
True
|
||||
|
||||
"""
|
||||
|
|
Loading…
Reference in New Issue