Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

queryset-refactor: Made sure the ordering columns in a distinct() que…

…ry only

include the columns we are selecting on. This avoids some PostgreSQL problems
and leads to more efficient queries to boot. Refs #5321.


git-svn-id: http://code.djangoproject.com/svn/django/branches/queryset-refactor@6515 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit 4c4341f01289e66f084d295236274a2e4556ae0d 1 parent e9364c0
@malcolmt malcolmt authored
View
26 django/db/models/sql/query.py
@@ -342,16 +342,22 @@ def get_columns(self):
"""
qn = self.quote_name_unless_alias
result = []
+ aliases = []
if self.select:
for col in self.select:
if isinstance(col, (list, tuple)):
- result.append('%s.%s' % (qn(col[0]), qn(col[1])))
+ r = '%s.%s' % (qn(col[0]), qn(col[1]))
+ result.append(r)
+ aliases.append(r)
else:
result.append(col.as_sql(quote_func=qn))
+ if hasattr(col, 'alias'):
+ aliases.append(col.alias)
else:
table_alias = self.tables[0]
result = ['%s.%s' % (qn(table_alias), qn(f.column))
for f in self.model._meta.fields]
+ aliases = result[:]
# We sort extra_select so that the result columns are in a well-defined
# order (and thus QuerySet.iterator can extract them correctly).
@@ -359,6 +365,9 @@ def get_columns(self):
extra_select.sort()
result.extend(['(%s) AS %s' % (col, alias)
for alias, col in extra_select])
+ aliases.extend(self.extra_select.keys())
+
+ self._select_aliases = dict.fromkeys(aliases)
return result
def get_from_clause(self):
@@ -435,6 +444,8 @@ def get_ordering(self):
# is handled in the previous test.
ordering = self.order_by or self.model._meta.ordering
qn = self.quote_name_unless_alias
+ distinct = self.distinct
+ select_aliases = self._select_aliases
result = []
for field in ordering:
if field == '?':
@@ -454,17 +465,22 @@ def get_ordering(self):
# necessary.
col, order = get_order_dir(field)
table, col = col.split('.', 1)
- result.append('%s.%s %s' % (qn(self.table_alias(table)[0]), col,
- order))
+ elt = '%s.%s' % (qn(self.table_alias(table)[0]), col)
+ if not distinct or elt in select_aliases:
+ result.append('%s %s' % (elt, order))
elif get_order_dir(field)[0] not in self.extra_select:
# 'col' is of the form 'field' or 'field1__field2' or
# 'field1__field2__field', etc.
for table, col, order in self.find_ordering_name(field,
self.model._meta):
- result.append('%s.%s %s' % (qn(table), qn(col), order))
+ elt = '%s.%s' % (qn(table), qn(col))
+ if not distinct or elt in select_aliases:
+ result.append('%s %s' % (elt, order))
else:
col, order = get_order_dir(field)
- result.append('%s %s' % (qn(col), order))
+ elt = qn(col)
+ if not distinct or elt in select_aliases:
+ result.append('%s %s' % (elt, order))
return result
def find_ordering_name(self, name, opts, alias=None, default_order='ASC'):
View
11 tests/regressiontests/queries/models.py
@@ -14,6 +14,7 @@ def __unicode__(self):
class Note(models.Model):
note = models.CharField(maxlength=100)
+ misc = models.CharField(maxlength=10)
class Meta:
ordering = ['note']
@@ -91,11 +92,11 @@ def __unicode__(self):
>>> t5 = Tag(name='t5', parent=t3)
>>> t5.save()
->>> n1 = Note(note='n1')
+>>> n1 = Note(note='n1', misc='foo')
>>> n1.save()
->>> n2 = Note(note='n2')
+>>> n2 = Note(note='n2', misc='bar')
>>> n2.save()
->>> n3 = Note(note='n3')
+>>> n3 = Note(note='n3', misc='foo')
>>> n3.save()
Create these out of order so that sorting by 'id' will be different to sorting
@@ -329,5 +330,9 @@ def __unicode__(self):
Bug #3037
>>> Item.objects.filter(Q(creator__name='a3', name='two')|Q(creator__name='a4', name='four'))
[<Item: four>]
+
+Bug #5321
+>>> Note.objects.values('misc').distinct().order_by('note', '-misc')
+[{'misc': u'foo'}, {'misc': u'bar'}]
"""}
Please sign in to comment.
Something went wrong with that request. Please try again.