Fixed #9406 -- Ensure that each database column is only represented once in the

"ORDER BY" clause of an SQL statement.


git-svn-id: http://code.djangoproject.com/svn/django/trunk@9251 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Malcolm Tredinnick 2008-10-24 06:09:47 +00:00
parent e3aa9a2828
commit 9319dc496c
2 changed files with 27 additions and 7 deletions

View File

@ -621,6 +621,12 @@ class Query(object):
asc, desc = ORDER_DIR['ASC'] asc, desc = ORDER_DIR['ASC']
else: else:
asc, desc = ORDER_DIR['DESC'] asc, desc = ORDER_DIR['DESC']
# It's possible, due to model inheritance, that normal usage might try
# to include the same field more than once in the ordering. We track
# the table/column pairs we use and discard any after the first use.
processed_pairs = set()
for field in ordering: for field in ordering:
if field == '?': if field == '?':
result.append(self.connection.ops.random_function_sql()) result.append(self.connection.ops.random_function_sql())
@ -638,18 +644,22 @@ class Query(object):
# on verbatim. # on verbatim.
col, order = get_order_dir(field, asc) col, order = get_order_dir(field, asc)
table, col = col.split('.', 1) table, col = col.split('.', 1)
elt = '%s.%s' % (qn(table), col) if (table, col) not in processed_pairs:
if not distinct or elt in select_aliases: elt = '%s.%s' % (qn(table), col)
result.append('%s %s' % (elt, order)) processed_pairs.add((table, 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: elif get_order_dir(field)[0] not in self.extra_select:
# 'col' is of the form 'field' or 'field1__field2' or # 'col' is of the form 'field' or 'field1__field2' or
# '-field1__field2__field', etc. # '-field1__field2__field', etc.
for table, col, order in self.find_ordering_name(field, for table, col, order in self.find_ordering_name(field,
self.model._meta, default_order=asc): self.model._meta, default_order=asc):
elt = '%s.%s' % (qn(table), qn2(col)) if (table, col) not in processed_pairs:
if distinct and elt not in select_aliases: elt = '%s.%s' % (qn(table), qn2(col))
ordering_aliases.append(elt) processed_pairs.add((table, col))
result.append('%s %s' % (elt, order)) if distinct and elt not in select_aliases:
ordering_aliases.append(elt)
result.append('%s %s' % (elt, order))
else: else:
col, order = get_order_dir(field, asc) col, order = get_order_dir(field, asc)
elt = qn2(col) elt = qn2(col)

View File

@ -257,4 +257,14 @@ DoesNotExist: ArticleWithAuthor matching query does not exist.
# without error. # without error.
>>> _ = QualityControl.objects.create(headline="Problems in Django", pub_date=datetime.datetime.now(), quality=10, assignee="adrian") >>> _ = QualityControl.objects.create(headline="Problems in Django", pub_date=datetime.datetime.now(), quality=10, assignee="adrian")
# Ordering should not include any database column more than once (this is most
# likely to ocurr naturally with model inheritance, so we check it here).
# Regression test for #9390. This necessarily pokes at the SQL string for the
# query, since the duplicate problems are only apparent at that late stage.
>>> sql = ArticleWithAuthor.objects.order_by('pub_date', 'pk').query.as_sql()[0]
>>> fragment = sql[sql.find('ORDER BY'):]
>>> pos = fragment.find('pub_date')
>>> fragment.find('pub_date', pos + 1) == -1
True
"""} """}