From b86bb47818e159e8db7e524ed8ef055b569ea111 Mon Sep 17 00:00:00 2001 From: Sergey Fedoseev Date: Mon, 14 Jan 2019 20:28:11 +0500 Subject: [PATCH] Fixed #30093 -- Fixed ordering of combined queryset ordered by F expressions. --- django/db/models/sql/compiler.py | 7 +++---- tests/queries/test_qs_combinators.py | 5 +++++ 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/django/db/models/sql/compiler.py b/django/db/models/sql/compiler.py index 30fb1418ab..3e04a801e9 100644 --- a/django/db/models/sql/compiler.py +++ b/django/db/models/sql/compiler.py @@ -339,8 +339,9 @@ class SQLCompiler: seen = set() for expr, is_ref in order_by: + resolved = expr.resolve_expression(self.query, allow_joins=True, reuse=None) if self.query.combinator: - src = expr.get_source_expressions()[0] + src = resolved.get_source_expressions()[0] # Relabel order by columns to raw numbers if this is a combined # query; necessary since the columns can't be referenced by the # fully qualified name and the simple column names may collide. @@ -350,12 +351,10 @@ class SQLCompiler: elif col_alias: continue if src == sel_expr: - expr.set_source_expressions([RawSQL('%d' % (idx + 1), ())]) + resolved.set_source_expressions([RawSQL('%d' % (idx + 1), ())]) break else: raise DatabaseError('ORDER BY term does not match any column in the result set.') - resolved = expr.resolve_expression( - self.query, allow_joins=True, reuse=None) sql, params = self.compile(resolved) # Don't add the same column twice, but the order direction is # not taken into account so we strip it. When this entire method diff --git a/tests/queries/test_qs_combinators.py b/tests/queries/test_qs_combinators.py index 8a928ba91f..3902db59e2 100644 --- a/tests/queries/test_qs_combinators.py +++ b/tests/queries/test_qs_combinators.py @@ -110,6 +110,11 @@ class QuerySetSetOperationTests(TestCase): qs2 = Number.objects.filter(num__gte=2, num__lte=3) self.assertNumbersEqual(qs1.union(qs2).order_by('-num'), [3, 2, 1, 0]) + def test_ordering_by_f_expression(self): + qs1 = Number.objects.filter(num__lte=1) + qs2 = Number.objects.filter(num__gte=2, num__lte=3) + self.assertNumbersEqual(qs1.union(qs2).order_by(F('num').desc()), [3, 2, 1, 0]) + def test_union_with_values(self): ReservedName.objects.create(name='a', order=2) qs1 = ReservedName.objects.all()