diff options
| author | Simon Charette <charette.s@gmail.com> | 2025-01-19 21:35:50 -0500 |
|---|---|---|
| committer | Sarah Boyce <42296566+sarahboyce@users.noreply.github.com> | 2025-01-21 09:09:43 +0100 |
| commit | 626d77e52a3f247358514bcf51c761283968099c (patch) | |
| tree | 439df5dcf465c18a4ca73bf9982be3cea46906f9 /tests/foreign_object/tests.py | |
| parent | 337c641abb36b3c2501b14e1290b800831bb20ad (diff) | |
Fixed #36116 -- Optimized multi-column ForwardManyToOne prefetching.
Rely on ColPairs and TupleIn which support a single column to be specified
to avoid special casing ForwardManyToOne.get_prefetch_querysets().
Thanks Jacob Walls for the report.
Diffstat (limited to 'tests/foreign_object/tests.py')
| -rw-r--r-- | tests/foreign_object/tests.py | 39 |
1 files changed, 36 insertions, 3 deletions
diff --git a/tests/foreign_object/tests.py b/tests/foreign_object/tests.py index 23ad546cd8..a0ea43677e 100644 --- a/tests/foreign_object/tests.py +++ b/tests/foreign_object/tests.py @@ -4,7 +4,7 @@ import pickle from operator import attrgetter from django.core.exceptions import FieldError -from django.db import models +from django.db import connection, models from django.test import SimpleTestCase, TestCase, skipUnlessDBFeature from django.test.utils import isolate_apps from django.utils import translation @@ -246,7 +246,7 @@ class MultiColumnFKTests(TestCase): normal_people = [m.person for m in Membership.objects.order_by("pk")] self.assertEqual(people, normal_people) - def test_prefetch_foreignkey_forward_works(self): + def test_prefetch_foreignobject_forward(self): Membership.objects.create( membership_country=self.usa, person=self.bob, group=self.cia ) @@ -263,7 +263,40 @@ class MultiColumnFKTests(TestCase): normal_people = [m.person for m in Membership.objects.order_by("pk")] self.assertEqual(people, normal_people) - def test_prefetch_foreignkey_reverse_works(self): + def test_prefetch_foreignobject_hidden_forward(self): + Friendship.objects.create( + from_friend_country=self.usa, + from_friend_id=self.bob.id, + to_friend_country_id=self.usa.id, + to_friend_id=self.george.id, + ) + Friendship.objects.create( + from_friend_country=self.usa, + from_friend_id=self.bob.id, + to_friend_country_id=self.soviet_union.id, + to_friend_id=self.sam.id, + ) + with self.assertNumQueries(2) as ctx: + friendships = list( + Friendship.objects.prefetch_related("to_friend").order_by("pk") + ) + prefetch_sql = ctx[-1]["sql"] + # Prefetch queryset should be filtered by all foreign related fields + # to prevent extra rows from being eagerly fetched. + prefetch_where_sql = prefetch_sql.split("WHERE")[-1] + for to_field_name in Friendship.to_friend.field.to_fields: + to_field = Person._meta.get_field(to_field_name) + with self.subTest(to_field=to_field): + self.assertIn( + connection.ops.quote_name(to_field.column), + prefetch_where_sql, + ) + self.assertNotIn(" JOIN ", prefetch_sql) + with self.assertNumQueries(0): + self.assertEqual(friendships[0].to_friend, self.george) + self.assertEqual(friendships[1].to_friend, self.sam) + + def test_prefetch_foreignobject_reverse(self): Membership.objects.create( membership_country=self.usa, person=self.bob, group=self.cia ) |
