From b52e45193f25e8444d3d5eef4f83d0ee8f7a80b0 Mon Sep 17 00:00:00 2001 From: Malcolm Tredinnick Date: Fri, 24 Oct 2008 06:11:37 +0000 Subject: [PATCH] [1.0.X] Fixed #9406 -- Ensure that each database column is only represented once in the "ORDER BY" clause of an SQL statement. Backport of r9251 from trunk. git-svn-id: http://code.djangoproject.com/svn/django/branches/releases/1.0.X@9252 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- django/db/models/sql/query.py | 24 +++++++++++++------ .../model_inheritance_regress/models.py | 10 ++++++++ 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/django/db/models/sql/query.py b/django/db/models/sql/query.py index 01fbd3d002..ee63a0214f 100644 --- a/django/db/models/sql/query.py +++ b/django/db/models/sql/query.py @@ -621,6 +621,12 @@ class Query(object): asc, desc = ORDER_DIR['ASC'] else: 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: if field == '?': result.append(self.connection.ops.random_function_sql()) @@ -638,18 +644,22 @@ class Query(object): # on verbatim. col, order = get_order_dir(field, asc) table, col = col.split('.', 1) - elt = '%s.%s' % (qn(table), col) - if not distinct or elt in select_aliases: - result.append('%s %s' % (elt, order)) + if (table, col) not in processed_pairs: + elt = '%s.%s' % (qn(table), col) + 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: # '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, default_order=asc): - elt = '%s.%s' % (qn(table), qn2(col)) - if distinct and elt not in select_aliases: - ordering_aliases.append(elt) - result.append('%s %s' % (elt, order)) + if (table, col) not in processed_pairs: + elt = '%s.%s' % (qn(table), qn2(col)) + processed_pairs.add((table, col)) + if distinct and elt not in select_aliases: + ordering_aliases.append(elt) + result.append('%s %s' % (elt, order)) else: col, order = get_order_dir(field, asc) elt = qn2(col) diff --git a/tests/regressiontests/model_inheritance_regress/models.py b/tests/regressiontests/model_inheritance_regress/models.py index 2777d1f23a..06a886e0be 100644 --- a/tests/regressiontests/model_inheritance_regress/models.py +++ b/tests/regressiontests/model_inheritance_regress/models.py @@ -257,4 +257,14 @@ DoesNotExist: ArticleWithAuthor matching query does not exist. # without error. >>> _ = 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 + """}