diff --git a/django/db/models/sql/query.py b/django/db/models/sql/query.py index 2548d631007..8cf3f581055 100644 --- a/django/db/models/sql/query.py +++ b/django/db/models/sql/query.py @@ -542,7 +542,10 @@ class Query(object): first = False for t in self.extra_tables: alias, unused = self.table_alias(t) - if alias not in self.alias_map: + # Only add the alias if it's not already present (the table_alias() + # calls increments the refcount, so an alias refcount of one means + # this is the only reference. + if alias not in self.alias_map or self.alias_refcount[alias] == 1: connector = not first and ', ' or '' result.append('%s%s' % (connector, qn(alias))) first = False diff --git a/tests/regressiontests/extra_regress/models.py b/tests/regressiontests/extra_regress/models.py index 8c624defc4d..500773d610a 100644 --- a/tests/regressiontests/extra_regress/models.py +++ b/tests/regressiontests/extra_regress/models.py @@ -24,6 +24,10 @@ class RevisionableModel(models.Model): new_revision.pk = None return new_revision +class Order(models.Model): + created_by = models.ForeignKey(User) + text = models.TextField() + __test__ = {"API_TESTS": """ # Regression tests for #7314 and #7372 @@ -87,4 +91,11 @@ True >>> qs[:1] [] +# Regression test for #8039: Ordering sometimes removed relevant tables from +# extra(). This test is the critical case: ordering uses a table, but then +# removes the reference because of an optimisation. The table should still be +# present because of the extra() call. +>>> Order.objects.extra(where=["username=%s"], params=["fred"], tables=["auth_user"]).order_by('created_by') +[] + """}