Skip to content

Commit

Permalink
Fixed #34267 -- Fixed sliced QuerySet.union() crash.
Browse files Browse the repository at this point in the history
Regression in 3d734c0.

Thanks Raphaël Stefanini for the report.
  • Loading branch information
panicofr authored and felixxm committed Jan 20, 2023
1 parent 79c298c commit cc8aa6b
Show file tree
Hide file tree
Showing 2 changed files with 12 additions and 7 deletions.
3 changes: 0 additions & 3 deletions django/db/models/sql/compiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -532,15 +532,12 @@ def get_combinator_sql(self, combinator, all):
"ORDER BY not allowed in subqueries of compound statements."
)
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 = ()
for compiler in compilers:
try:
Expand Down
16 changes: 12 additions & 4 deletions tests/queries/test_qs_combinators.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,15 @@ def test_union_combined_slice_compound_empty(self):
qs3 = qs1.union(qs2)
self.assertNumbersEqual(qs3.order_by("num")[2:3], [2])

def test_union_slice_index(self):
Celebrity.objects.create(name="Famous")
c1 = Celebrity.objects.create(name="Very famous")

qs1 = Celebrity.objects.filter(name="nonexistent")
qs2 = Celebrity.objects.all()
combined_qs = qs1.union(qs2).order_by("name")
self.assertEqual(combined_qs[1], c1)

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)
Expand Down Expand Up @@ -319,10 +328,10 @@ def test_union_with_select_related_and_first(self):
e1 = ExtraInfo.objects.create(value=7, info="e1")
a1 = Author.objects.create(name="a1", num=1, extra=e1)
Author.objects.create(name="a2", num=3, extra=e1)
base_qs = Author.objects.select_related("extra")
base_qs = Author.objects.select_related("extra").order_by()
qs1 = base_qs.filter(name="a1")
qs2 = base_qs.filter(name="a2")
self.assertEqual(qs1.union(qs2).first(), a1)
self.assertEqual(qs1.union(qs2).order_by("name").first(), a1)

def test_union_with_first(self):
e1 = ExtraInfo.objects.create(value=7, info="e1")
Expand Down Expand Up @@ -455,8 +464,7 @@ def test_exists_union(self):
captured_sql,
)
self.assertEqual(
captured_sql.count(connection.ops.limit_offset_sql(None, 1)),
3 if connection.features.supports_slicing_ordering_in_compound else 1,
captured_sql.count(connection.ops.limit_offset_sql(None, 1)), 1
)

def test_exists_union_empty_result(self):
Expand Down

0 comments on commit cc8aa6b

Please sign in to comment.