#36109: Three or more stacked FilteredRelations can create a RecursionError
-------------------------------------+-------------------------------------
     Reporter:  Peter DeVita         |                     Type:  Bug
       Status:  new                  |                Component:  Database
                                     |  layer (models, ORM)
      Version:  5.1                  |                 Severity:  Normal
     Keywords:  FilteredRelation     |             Triage Stage:
                                     |  Unreviewed
    Has patch:  1                    |      Needs documentation:  0
  Needs tests:  0                    |  Patch needs improvement:  0
Easy pickings:  0                    |                    UI/UX:  0
-------------------------------------+-------------------------------------
 Example test case, this belongs to FilteredRelationTests

 {{{
     def test_three_level_nested_chained_relations(self):
         borrower1 = Borrower.objects.create(name="Jenny")
         # borrower 1 reserves, rents, and returns book1.
         Reservation.objects.create(
             borrower=borrower1,
             book=self.book1,
             state=Reservation.STOPPED,
         )
         qs = (
             Author.objects.annotate(
                 my_books=FilteredRelation(
                     "book"
                 ),
                 my_reserved_books=FilteredRelation(
                     "my_books__reservation",
 condition=Q(my_books__reservation__state=Reservation.STOPPED)
                 ),
                 my_readers=FilteredRelation(
                     "my_reserved_books__borrower",
                     condition=Q(my_reserved_books__borrower=borrower1)
                 )
             )
         )
         qs = qs.filter(
             my_readers=borrower1
         )
         self.assertQuerySetEqual(
             qs,
             [
                 ("Alice",)
             ],
             lambda x: (x.name,),
         )
 }}}

 This will result in a {{{RecursionError}}} when the filter is applied.
 From what I can understand, this is because on {{{Query}}} when it gets to
 {{{setup_joins}}} and attempts to setup the join for the {{{my_readers}}}
 FilteredRelation, it is not allowed to reuse the aliases from the first
 two `FilteredRelation`s. It then constantly recurses, trying to setup the
 joins and then not being able to reuse the joins.

 I'm no ORM expert but the fix might be as simple as just adding the
 FilteredRelation's join alias to the {{{can_reuse}}} set. Any joins that
 were going to that table but not through the FilteredRelation should be
 unaffected since they weren't going to reference its alias anyways. Any
 joins that do reference that FilteredRelation should always want to reuse
 this too. The fix is in my diff/PR and tests all pass with it.

 This bug might also be only because we're filtering on the last join in
 the set as the first filter condition, it might be possible to force the
 aliases to be reusable if you filtered one at a time on each
 FilteredRelation leading up to it.
-- 
Ticket URL: <https://code.djangoproject.com/ticket/36109>
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 view this discussion visit 
https://groups.google.com/d/msgid/django-updates/01070194757c7b50-80f8a1fd-5543-475c-a2ec-b689e1db407b-000000%40eu-central-1.amazonses.com.

Reply via email to