Fixed #31614 -- Fixed aliases ordering by OrderBy() expressions of combined queryset.
This commit is contained in:
parent
51ad767d0b
commit
2aac176e86
|
@ -6,7 +6,7 @@ from itertools import chain
|
||||||
from django.core.exceptions import EmptyResultSet, FieldError
|
from django.core.exceptions import EmptyResultSet, FieldError
|
||||||
from django.db import DatabaseError, NotSupportedError
|
from django.db import DatabaseError, NotSupportedError
|
||||||
from django.db.models.constants import LOOKUP_SEP
|
from django.db.models.constants import LOOKUP_SEP
|
||||||
from django.db.models.expressions import OrderBy, Random, RawSQL, Ref, Value
|
from django.db.models.expressions import F, OrderBy, Random, RawSQL, Ref, Value
|
||||||
from django.db.models.functions import Cast
|
from django.db.models.functions import Cast
|
||||||
from django.db.models.query_utils import Q, select_related_descend
|
from django.db.models.query_utils import Q, select_related_descend
|
||||||
from django.db.models.sql.constants import (
|
from django.db.models.sql.constants import (
|
||||||
|
@ -361,13 +361,16 @@ class SQLCompiler:
|
||||||
resolved = expr.resolve_expression(self.query, allow_joins=True, reuse=None)
|
resolved = expr.resolve_expression(self.query, allow_joins=True, reuse=None)
|
||||||
if self.query.combinator:
|
if self.query.combinator:
|
||||||
src = resolved.get_source_expressions()[0]
|
src = resolved.get_source_expressions()[0]
|
||||||
|
expr_src = expr.get_source_expressions()[0]
|
||||||
# Relabel order by columns to raw numbers if this is a combined
|
# Relabel order by columns to raw numbers if this is a combined
|
||||||
# query; necessary since the columns can't be referenced by the
|
# query; necessary since the columns can't be referenced by the
|
||||||
# fully qualified name and the simple column names may collide.
|
# fully qualified name and the simple column names may collide.
|
||||||
for idx, (sel_expr, _, col_alias) in enumerate(self.select):
|
for idx, (sel_expr, _, col_alias) in enumerate(self.select):
|
||||||
if is_ref and col_alias == src.refs:
|
if is_ref and col_alias == src.refs:
|
||||||
src = src.source
|
src = src.source
|
||||||
elif col_alias:
|
elif col_alias and not (
|
||||||
|
isinstance(expr_src, F) and col_alias == expr_src.name
|
||||||
|
):
|
||||||
continue
|
continue
|
||||||
if src == sel_expr:
|
if src == sel_expr:
|
||||||
resolved.set_source_expressions([RawSQL('%d' % (idx + 1), ())])
|
resolved.set_source_expressions([RawSQL('%d' % (idx + 1), ())])
|
||||||
|
|
|
@ -123,6 +123,21 @@ class QuerySetSetOperationTests(TestCase):
|
||||||
qs2 = Number.objects.filter(num__gte=2, num__lte=3)
|
qs2 = Number.objects.filter(num__gte=2, num__lte=3)
|
||||||
self.assertNumbersEqual(qs1.union(qs2).order_by(F('num').desc()), [3, 2, 1, 0])
|
self.assertNumbersEqual(qs1.union(qs2).order_by(F('num').desc()), [3, 2, 1, 0])
|
||||||
|
|
||||||
|
def test_ordering_by_f_expression_and_alias(self):
|
||||||
|
qs1 = Number.objects.filter(num__lte=1).values(alias=F('other_num'))
|
||||||
|
qs2 = Number.objects.filter(num__gte=2, num__lte=3).values(alias=F('other_num'))
|
||||||
|
self.assertQuerysetEqual(
|
||||||
|
qs1.union(qs2).order_by(F('alias').desc()),
|
||||||
|
[10, 9, 8, 7],
|
||||||
|
operator.itemgetter('alias'),
|
||||||
|
)
|
||||||
|
Number.objects.create(num=-1)
|
||||||
|
self.assertQuerysetEqual(
|
||||||
|
qs1.union(qs2).order_by(F('alias').desc(nulls_last=True)),
|
||||||
|
[10, 9, 8, 7, None],
|
||||||
|
operator.itemgetter('alias'),
|
||||||
|
)
|
||||||
|
|
||||||
def test_union_with_values(self):
|
def test_union_with_values(self):
|
||||||
ReservedName.objects.create(name='a', order=2)
|
ReservedName.objects.create(name='a', order=2)
|
||||||
qs1 = ReservedName.objects.all()
|
qs1 = ReservedName.objects.all()
|
||||||
|
|
Loading…
Reference in New Issue