-
-
Notifications
You must be signed in to change notification settings - Fork 33.2k
Fixed #20024 -- Corrected handling of __in lookups with None in exclude querysets to match SQL semantics. #20027
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
base: main
Are you sure you want to change the base?
Conversation
jacobtylerwalls
left a comment
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.
Thanks for the PR!
@charettes reviewed #19691, so he might have some thoughts.
charettes
left a comment
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.
Looks like the right approach to me!
…lude(). Thanks Simon Charette for the review and Jason Hall for a prior iteration.
3de9ddd to
c26fbd5
Compare
jacobtylerwalls
left a comment
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.
Thanks! I reorganized commits slightly (one adding coverage with Refs # and the one fixing the bug and testing it with Fixed #.)
Welcome aboard! ⛵
|
buildbot, test on oracle. |
| def setUpTestData(cls): | ||
| cls.tenant = Tenant.objects.create() | ||
| cls.user = User.objects.create( | ||
| tenant=cls.tenant, id=1, email="[email protected]" |
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.
Avoid hardcoding primary key values
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.
Sure. But, considering that the User model in this module uses a composite primary key and auto assignment is not allowed, I have to provide an id when creating the user. The previous tests in this file are handling primary key values in the same way.
Still, your observation applies to the tuples, and I'm considering updating them.
| if ( | ||
| lookup_type == "in" | ||
| and isinstance(condition.rhs, Iterable) | ||
| and not isinstance(condition.rhs, (str, bytes)) | ||
| and any(v is None for v in condition.rhs) | ||
| ): | ||
| clause.add(lookup_class(col, True), OR) |
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.
This monstrosity seems to merit an explanatory comment.
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.
Sure, it does look a bit monstrous. In short, it targets in lookups where the rhs iterable (non-string) contains None. If you have any suggestion to simplify the condition, please let me know.
In the first comment, the issue I'm highlighting from the sql generated is that AND is generated instead of OR, on the other hand IS NOT NULL is generated instead of IS NULL.
clause.add(lookup_class(col, True), OR) corrects this behavior using True to generate IS NULL with OR connector.
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.
I think Tim is encouraging adding a comment above this if block in the code.
| def test_pk_in_with_partial_or_all_none(self): | ||
| qs = User.objects | ||
| self.assertQuerySetEqual(qs.filter(pk__in=[(1, None)]), []) | ||
| self.assertQuerySetEqual(qs.filter(pk__in=[(None, None)]), []) | ||
| self.assertQuerySetEqual(qs.exclude(pk__in=[(1, None)]), [self.user]) | ||
| self.assertQuerySetEqual(qs.exclude(pk__in=[(None, None)]), [self.user]) |
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.
If you're going to use a test class for this, perhaps each assertion could be its own method.
Trac ticket number
ticket-20024
Branch description
Problem
The SQL generated by an exclude queryset is not semantically aligned with the queryset when using
__inlookups containingNone.Solution
The PR updates
WhereNodeto useORand generateIS NULLfor correct SQL semantics in this case.Checklist
mainbranch.