Opened 3 weeks ago

Last modified 3 weeks ago

#37383 assigned Bug

Add support for using F("pk") as the LHS of a tuple lookup when the RHS is a Query

Reported by: Jacob Walls Owned by: Vishy
Component: Database layer (models, ORM) Version: dev
Severity: Normal Keywords: CompositePrimaryKey
Cc: Simon Charette Triage Stage: Accepted
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

The fix for #37291 fixes a hang when using F("pk") with tuple lookups.

The preliminary fix results in ValueError, which is better than a hang. That much can be backported. This issue is for improving on the ValueError to return the correct result. In other words, this ticket is for removing these skips on these almost-identical tests:

# For TupleLookupsTests
    @unittest.expectedFailure
    def test_tuple_in_subquery_lhs_f_pk(self):
        self.assertCountEqual(
            Contact.objects.filter(
                TupleIn(F("pk"), Contact.objects.values("customer").query)
            ),
            Contact.objects.all(),
        )
# For CompositePKLookupsTests
    @unittest.expectedFailure
    def test_filter_by_pk_in_rhs_f_object_lhs(self):
        self.assertCountEqual(
            Comment.objects.filter(
                TupleIn(F("pk"), Comment.objects.values("pk").query)
            ),
            Comment.objects.all(),
        )

See

======================================================================
ERROR: test_tuple_in_subquery_lhs_f_pk (foreign_object.test_tuple_lookups.TupleLookupsTests.test_tuple_in_subquery_lhs_f_pk)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/Users/jwalls/django/tests/foreign_object/test_tuple_lookups.py", line 174, in test_tuple_in_subquery_lhs_f_pk
    TupleIn(F("pk"), Contact.objects.values("customer").query)
    ~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/jwalls/django/django/db/models/lookups.py", line 36, in __init__
    self.rhs = self.get_prep_lookup()
               ~~~~~~~~~~~~~~~~~~~~^^
  File "/Users/jwalls/django/django/db/models/fields/tuple_lookups.py", line 310, in get_prep_lookup
    super(TupleLookupMixin, self).get_prep_lookup()
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^
  File "/Users/jwalls/django/django/db/models/lookups.py", line 512, in get_prep_lookup
    raise ValueError(
    ...<2 lines>...
    )
ValueError: The QuerySet value for the 'in' lookup must have 1 selected fields (received 2)

We don't have access to the query for resolution of F("pk") during the get_prep_lookup() above, so I'm not immediately sure how to solve this.

Change History (4)

comment:1 by Vishy, 3 weeks ago

Owner: set to Vishy
Status: new → assigned

comment:2 by Natalia Bidart, 3 weeks ago

Cc: Simon Charette added

Hey Jacob, thanks for the ticket and clear explanation, though it all screams New feature. Could you help me understand why you filed it under Bug?

comment:3 by Jacob Walls, 3 weeks ago

Sure -- I don't see this as about some feature area that was not supported / not considered. Composite primary keys were implemented as the pk = ... field, and F("pk") works all over the place. In fact, it even works here if you comment out the len() safety check in TupleIn.get_prep_lookup(). So in my opinion this just a bug in the len() safety check -- it either takes place too early, or it needs to be repeated at a later point after F("pk") is resolved, or ...?

comment:4 by Natalia Bidart, 3 weeks ago

Triage Stage: Unreviewed → Accepted

Thanks, that helps. Accepting on that basis!

Note: See TracTickets for help on using tickets.
Back to Top