#26318: Unexpected / duplicated queries on nested Prefetch queryset with 
repeated
model
-------------------------------------+-------------------------------------
     Reporter:  aleontiev            |      Owner:  nobody
         Type:  Bug                  |     Status:  new
    Component:  Database layer       |    Version:  master
  (models, ORM)                      |   Keywords:  queryset
     Severity:  Normal               |  prefetch_related duplicate
 Triage Stage:  Unreviewed           |  Has patch:  0
Easy pickings:  0                    |      UI/UX:  0
-------------------------------------+-------------------------------------
 We discovered an issue in {{{django.db.models.query.Prefetch}}} logic that
 results in duplicate queries made when the leaves of certain prefetch
 trees are accessed.

 With these models:

 {{{
 from django.db import models


 class Publisher(models.Model):
     name = models.CharField(max_length=128)


 class Author(models.Model):
     name = models.CharField(max_length=128)
     publishers = models.ManyToManyField('Publisher',
 related_name='authors')


 class Book(models.Model):
     name = models.CharField(max_length=128)
     publisher = models.ForeignKey('Publisher', related_name='books')
 }}}

 The following test fails:

 {{{
 from django.db.models.query import Prefetch
 from django.test import TestCase
 from .models import Author, Book, Publisher


 def flatten(ls):
     return list([i for s in ls for i in s])


 class PrefetchTestCase(TestCase):

     def setUp(self):
         publisher = Publisher.objects.create(name='Publisher0')
         Book.objects.create(name='Book0', publisher=publisher)
         author = Author.objects.create(name='Author0')
         author.publishers.add(publisher)

     def test_prefetch_nested(self):
         publishers = Publisher.objects.prefetch_related(
             Prefetch(
                 'books',
                 Book.objects.all().prefetch_related(
                     Prefetch(
                         'publisher',
 Publisher.objects.all().prefetch_related('authors')
                     )
                 )
             )
         )
         with self.assertNumQueries(4):
             publishers = list(publishers)

         with self.assertNumQueries(0):
             books = flatten([p.books.all() for p in publishers])
         with self.assertNumQueries(0):
             publishers = [b.publisher for b in books]
         with self.assertNumQueries(0):
             authors = flatten([p.authors.all() for p in publishers])
 }}}

 For more details (comments, queries executed) and an analogous green test-
 case that uses the flat prefetch form to prefetch the same tree, see the
 attached test package.

 To run the tests:

 {{{
         tar -zxvf prefetch-bug-test.tar.gz
         cd prefetch-bug-test
         make test
 }}}

 This issue seemed very similar to
 https://code.djangoproject.com/ticket/25546, but unfortunately the patch
 for that ticket
 
(https://code.djangoproject.com/changeset/bdbe50a491ca41e7d4ebace47bfe8abe50a58211)
 did not fix this problem.

 Tested in Django 1.8, 1.9, and master.

--
Ticket URL: <https://code.djangoproject.com/ticket/26318>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/052.f26185adda9a5444973b704c6e551689%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to