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:
parent
543e17c440
commit
f7f38f3a0b
@ -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)
|
||||
|
||||
|
||||
|
@ -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`).
|
||||
|
@ -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"),
|
||||
|
@ -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(
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user