mirror of https://github.com/django/django.git
Fixed #34125 -- Fixed sliced QuerySet.union() crash on a single non-empty queryset.
The bug existed since sliced query union was added but was elevated to
query union slices by moving the .exists() optimization to the compiler
in 3d734c09ff
.
Thanks Stefan Hammer for the report.
This commit is contained in:
parent
09397f5cfa
commit
c2cc80756b
|
@ -531,7 +531,6 @@ class SQLCompiler:
|
|||
compilers = [
|
||||
query.get_compiler(self.using, self.connection, self.elide_empty)
|
||||
for query in self.query.combined_queries
|
||||
if not query.is_empty()
|
||||
]
|
||||
if not features.supports_slicing_ordering_in_compound:
|
||||
for compiler in compilers:
|
||||
|
@ -546,6 +545,11 @@ class SQLCompiler:
|
|||
elif self.query.is_sliced and combinator == "union":
|
||||
limit = (self.query.low_mark, self.query.high_mark)
|
||||
for compiler in compilers:
|
||||
# A sliced union cannot have its parts elided as some of them
|
||||
# might be sliced as well and in the event where only a single
|
||||
# part produces a non-empty resultset it might be impossible to
|
||||
# generate valid SQL.
|
||||
compiler.elide_empty = False
|
||||
if not compiler.query.is_sliced:
|
||||
compiler.query.set_limits(*limit)
|
||||
parts = ()
|
||||
|
|
|
@ -61,6 +61,32 @@ class QuerySetSetOperationTests(TestCase):
|
|||
self.assertSequenceEqual(qs3.none(), [])
|
||||
self.assertNumbersEqual(qs3, [0, 1, 8, 9], ordered=False)
|
||||
|
||||
def test_union_none_slice(self):
|
||||
qs1 = Number.objects.filter(num__lte=0)
|
||||
qs2 = Number.objects.none()
|
||||
qs3 = qs1.union(qs2)
|
||||
self.assertNumbersEqual(qs3[:1], [0])
|
||||
|
||||
def test_union_empty_filter_slice(self):
|
||||
qs1 = Number.objects.filter(num__lte=0)
|
||||
qs2 = Number.objects.filter(pk__in=[])
|
||||
qs3 = qs1.union(qs2)
|
||||
self.assertNumbersEqual(qs3[:1], [0])
|
||||
|
||||
@skipUnlessDBFeature("supports_slicing_ordering_in_compound")
|
||||
def test_union_slice_compound_empty(self):
|
||||
qs1 = Number.objects.filter(num__lte=0)[:1]
|
||||
qs2 = Number.objects.none()
|
||||
qs3 = qs1.union(qs2)
|
||||
self.assertNumbersEqual(qs3[:1], [0])
|
||||
|
||||
@skipUnlessDBFeature("supports_slicing_ordering_in_compound")
|
||||
def test_union_combined_slice_compound_empty(self):
|
||||
qs1 = Number.objects.filter(num__lte=2)[:3]
|
||||
qs2 = Number.objects.none()
|
||||
qs3 = qs1.union(qs2)
|
||||
self.assertNumbersEqual(qs3.order_by("num")[2:3], [2])
|
||||
|
||||
def test_union_order_with_null_first_last(self):
|
||||
Number.objects.filter(other_num=5).update(other_num=None)
|
||||
qs1 = Number.objects.filter(num__lte=1)
|
||||
|
|
Loading…
Reference in New Issue