-
-
Notifications
You must be signed in to change notification settings - Fork 128
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix(optimizer): Fix nested pagination optimization for m2m relations #681
Conversation
Reviewer's Guide by SourceryThis pull request fixes a bug in nested pagination optimization for many-to-many (m2m) relations in Django versions prior to 5.2. The bug occurs when annotating related objects in a prefetch queryset, causing Django to generate incorrect results. The fix involves monkey-patching older Django versions to address the issue. Sequence diagram for patched nested pagination optimization flowsequenceDiagram
participant Q as QuerySet
participant FP as _filter_prefetch_queryset
participant AQ as Query.add_q
Q->>FP: Filter prefetch queryset
Note over FP: Create predicate with field_name__in
Note over FP: Apply window functions if sliced
FP->>AQ: add_q(predicate, reuse_all_aliases=True)
Note over AQ: Use all existing aliases
Note over AQ: Add clause to WHERE conditions
AQ-->>FP: Return modified query
FP-->>Q: Return filtered queryset
Class diagram showing patched Django query componentsclassDiagram
class Query {
+add_q(q_object, reuse_all_aliases)
-_add_q(q_object, can_reuse)
+where
+alias_map
}
class _filter_prefetch_queryset {
+queryset
+field_name
+instances
}
class OptimizerExtension {
+enable_nested_relations_prefetch: bool
+prefetch_custom_queryset: bool
+on_execute()
}
OptimizerExtension ..> Query: uses
Query ..> _filter_prefetch_queryset: uses
note for OptimizerExtension "Applies pagination fix when nested relations prefetch is enabled"
note for Query "Patched to support alias reuse"
note for _filter_prefetch_queryset "Patched to use reuse_all_aliases"
File-Level Changes
Assessment against linked issues
Possibly linked issues
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey @bellini666 - I've reviewed your changes and they look great!
Here's what I looked at during the review
- 🟢 General issues: all looks good
- 🟢 Security: all looks good
- 🟡 Testing: 1 issue found
- 🟢 Complexity: all looks good
- 🟢 Documentation: all looks good
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #681 +/- ##
==========================================
- Coverage 89.17% 89.00% -0.18%
==========================================
Files 41 42 +1
Lines 3778 3819 +41
==========================================
+ Hits 3369 3399 +30
- Misses 409 420 +11 ☔ View full report in Codecov by Sentry. |
49a8908
to
1d893aa
Compare
When annotating something from the relation into the prefetch queryset for a m2m relation, Django will mistakenly not reuse the existing join and end up resulting in the generation of spurious results. There's an ongoing fix for this i this ticket: https://code.djangoproject.com/ticket/35677 This is monkey patching older versions of Django which doesn't contain the fix, and most likely won't (Django usually only backports security issues), to fix the issue. Thanks @SupImDos for providing an MRE in the form of a test for this! Fix #650
1d893aa
to
bbfcbf6
Compare
if django.VERSION >= (5, 2): | ||
return |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nice!
When annotating something from the relation into the prefetch queryset for a m2m relation, Django will mistakenly not reuse the existing join and end up resulting in the generation of spurious results.
There's an ongoing fix for this i this ticket: https://code.djangoproject.com/ticket/35677
This is monkey patching older versions of Django which doesn't contain the fix, and most likely won't (Django usually only backports security issues), to fix the issue.
Thanks @SupImDos for providing an MRE in the form of a test for this!
Fix #650
Summary by Sourcery
Fix nested pagination optimization for many-to-many relations in Django 5.1 or older by monkey-patching the
_filter_prefetch_queryset
andadd_q
methods to reuse existing aliases and joins.Bug Fixes:
Enhancements:
Tests: