[Django] #36109: Three or more stacked FilteredRelations can create a RecursionError

19 views
Skip to first unread message

Django

unread,
Jan 17, 2025, 1:18:06 PMJan 17
to django-...@googlegroups.com
#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.

Django

unread,
Jan 17, 2025, 1:18:30 PMJan 17
to django-...@googlegroups.com
#36109: Three or more stacked FilteredRelations can create a RecursionError
-------------------------------------+-------------------------------------
Reporter: Peter DeVita | Owner: (none)
Type: Bug | Status: new
Component: Database layer | Version: 5.1
(models, ORM) |
Severity: Normal | Resolution:
Keywords: FilteredRelation | Triage Stage:
| Unreviewed
Has patch: 1 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Peter DeVita):

* Attachment "filteredrelation_stack.diff" added.

Django

unread,
Jan 17, 2025, 9:23:16 PMJan 17
to django-...@googlegroups.com
#36109: Three or more stacked FilteredRelations can create a RecursionError
-------------------------------------+-------------------------------------
Reporter: Peter DeVita | Owner: Anirudh
| Konidala
Type: Bug | Status: assigned
Component: Database layer | Version: 5.1
(models, ORM) |
Severity: Normal | Resolution:
Keywords: FilteredRelation | Triage Stage:
| Unreviewed
Has patch: 1 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Anirudh Konidala):

* owner: (none) => Anirudh Konidala
* status: new => assigned

--
Ticket URL: <https://code.djangoproject.com/ticket/36109#comment:1>

Django

unread,
Jan 18, 2025, 4:21:01 PMJan 18
to django-...@googlegroups.com
#36109: Three or more stacked FilteredRelations can create a RecursionError
-------------------------------------+-------------------------------------
Reporter: Peter DeVita | Owner: Peter
| DeVita
Type: Bug | Status: assigned
Component: Database layer | Version: 5.1
(models, ORM) |
Severity: Normal | Resolution:
Keywords: FilteredRelation | Triage Stage:
| Unreviewed
Has patch: 1 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Peter DeVita):

* owner: Anirudh Konidala => Peter DeVita

Comment:

Ah I didn't realize how the ownership system works, my bad. Sorry Anirudh,
I already have a PR open for this so I'm going to reassign ownership to
myself.
--
Ticket URL: <https://code.djangoproject.com/ticket/36109#comment:2>

Django

unread,
Jan 19, 2025, 7:48:19 PMJan 19
to django-...@googlegroups.com
#36109: Three or more stacked FilteredRelations can create a RecursionError
-------------------------------------+-------------------------------------
Reporter: Peter DeVita | Owner: Peter
| DeVita
Type: Bug | Status: assigned
Component: Database layer | Version: 5.1
(models, ORM) |
Severity: Normal | Resolution:
Keywords: FilteredRelation | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Tim Graham):

* stage: Unreviewed => Accepted

--
Ticket URL: <https://code.djangoproject.com/ticket/36109#comment:3>

Django

unread,
Jan 22, 2025, 8:45:37 AMJan 22
to django-...@googlegroups.com
#36109: Three or more stacked FilteredRelations can create a RecursionError
-------------------------------------+-------------------------------------
Reporter: Peter DeVita | Owner: Peter
| DeVita
Type: Bug | Status: assigned
Component: Database layer | Version: 5.1
(models, ORM) |
Severity: Normal | Resolution:
Keywords: FilteredRelation | Triage Stage: Ready for
| checkin
Has patch: 1 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Sarah Boyce):

* stage: Accepted => Ready for checkin

--
Ticket URL: <https://code.djangoproject.com/ticket/36109#comment:4>

Django

unread,
Jan 27, 2025, 4:32:29 AMJan 27
to django-...@googlegroups.com
#36109: Three or more stacked FilteredRelations can create a RecursionError
-------------------------------------+-------------------------------------
Reporter: Peter DeVita | Owner: Peter
| DeVita
Type: Bug | Status: closed
Component: Database layer | Version: 5.1
(models, ORM) |
Severity: Normal | Resolution: fixed
Keywords: FilteredRelation | Triage Stage: Ready for
| checkin
Has patch: 1 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Sarah Boyce <42296566+sarahboyce@…>):

* resolution: => fixed
* status: assigned => closed

Comment:

In [changeset:"8eca4077f60fa0705ecfd9437c9ceaeef7a3808b" 8eca4077]:
{{{#!CommitTicketReference repository=""
revision="8eca4077f60fa0705ecfd9437c9ceaeef7a3808b"
Fixed #36109 -- Fixed RecursionError when stacking FilteredRelation joins.
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/36109#comment:5>

Django

unread,
Jan 27, 2025, 4:34:46 AMJan 27
to django-...@googlegroups.com
#36109: Three or more stacked FilteredRelations can create a RecursionError
-------------------------------------+-------------------------------------
Reporter: Peter DeVita | Owner: Peter
| DeVita
Type: Bug | Status: closed
Component: Database layer | Version: 5.1
(models, ORM) |
Severity: Normal | Resolution: fixed
Keywords: FilteredRelation | Triage Stage: Ready for
| checkin
Has patch: 1 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Comment (by Sarah Boyce <42296566+sarahboyce@…>):

In [changeset:"720ef7a867eab1491f5789fe39b3431a498b2b89" 720ef7a]:
{{{#!CommitTicketReference repository=""
revision="720ef7a867eab1491f5789fe39b3431a498b2b89"
[5.2.x] Fixed #36109 -- Fixed RecursionError when stacking
FilteredRelation joins.

Backport of 8eca4077f60fa0705ecfd9437c9ceaeef7a3808b from main.
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/36109#comment:6>
Reply all
Reply to author
Forward
0 new messages