1
0
mirror of https://github.com/django/django.git synced 2025-04-10 08:19:39 +00:00

Fixed #36290 -- Made TupleIn() lookup discard tuples containing None.

Just like the In() lookup discards of None members TupleIn() should
discard tuples containing any None as NULL != NULL in SQL and the
framework expects such queries to be elided under some circumstances.

Refs #31667, #36116.

Thanks Basptise Mispelon for bisecting the regression to 626d77e.
This commit is contained in:
Simon Charette 2025-04-02 13:32:38 -04:00 committed by Mariusz Felisiak
parent 543e17c440
commit f7f38f3a0b
5 changed files with 37 additions and 1 deletions

View File

@ -329,6 +329,10 @@ class TupleIn(TupleLookupMixin, In):
lhs = self.lhs
for vals in rhs:
# Remove any tuple containing None from the list as NULL is never
# equal to anything.
if any(val is None for val in vals):
continue
result.append(
Tuple(
*[
@ -338,6 +342,9 @@ class TupleIn(TupleLookupMixin, In):
)
)
if not result:
raise EmptyResultSet
return compiler.compile(Tuple(*result))
def get_fallback_sql(self, compiler, connection):
@ -353,9 +360,15 @@ class TupleIn(TupleLookupMixin, In):
lhs = self.lhs
for vals in rhs:
# Remove any tuple containing None from the list as NULL is never
# equal to anything.
if any(val is None for val in vals):
continue
lookups = [Exact(col, val) for col, val in zip(lhs, vals)]
root.children.append(WhereNode(lookups, connector=AND))
if not root.children:
raise EmptyResultSet
return root.as_sql(compiler, connection)

View File

@ -12,3 +12,6 @@ Bugfixes
* Fixed a regression in Django 5.2 that caused a crash when annotating
aggregate expressions over query that uses explicit grouping by transforms
followed by field references (:ticket:`36292`).
* Fixed a regression in Django 5.2 that caused unnecessary queries when
prefetching nullable foreign key relationships (:ticket:`36290`).

View File

@ -206,6 +206,13 @@ class CompositePKFilterTests(TestCase):
[self.comment_1],
)
def test_filter_by_pk_in_none(self):
with self.assertNumQueries(0):
self.assertSequenceEqual(
Comment.objects.filter(pk__in=[(None, 1), (1, None)]),
[],
)
def test_filter_comments_by_user_and_order_by_pk_asc(self):
self.assertSequenceEqual(
Comment.objects.filter(user=self.user_1).order_by("pk"),

View File

@ -84,7 +84,7 @@ class Friendship(models.Model):
)
from_friend_id = models.IntegerField()
to_friend_country_id = models.IntegerField()
to_friend_id = models.IntegerField()
to_friend_id = models.IntegerField(null=True)
# Relation Fields
from_friend = models.ForeignObject(

View File

@ -296,6 +296,19 @@ class MultiColumnFKTests(TestCase):
self.assertEqual(friendships[0].to_friend, self.george)
self.assertEqual(friendships[1].to_friend, self.sam)
def test_prefetch_foreignobject_null_hidden_forward_skipped(self):
fiendship = Friendship.objects.create(
from_friend_country=self.usa,
from_friend_id=self.bob.id,
to_friend_country_id=self.usa.id,
to_friend_id=None,
)
with self.assertNumQueries(1):
self.assertEqual(
Friendship.objects.prefetch_related("to_friend").get(),
fiendship,
)
def test_prefetch_foreignobject_reverse(self):
Membership.objects.create(
membership_country=self.usa, person=self.bob, group=self.cia