mirror of
https://github.com/django/django.git
synced 2025-02-08 00:16:31 +00:00
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 3d734c09ff0138441dfe0a59010435871d17950f. 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…
x
Reference in New Issue
Block a user