#36149: Composite primary key subquery lookup prevent usage or specify fields and
are not implemented for exact
-------------------------------------+-------------------------------------
Reporter: Simon | Owner: (none)
Charette |
Type: Bug | Status: assigned
Component: Database | Version: 5.2
layer (models, ORM) |
Severity: Release | Keywords:
blocker |
Triage Stage: | Has patch: 1
Unreviewed |
Needs documentation: 0 | Needs tests: 0
Patch needs improvement: 0 | Easy pickings: 0
UI/UX: 0 |
-------------------------------------+-------------------------------------
I started playing with tuple lookup support for composite primary key and
I noticed two main problems.
First `pk__in=query` lookups completely disallow specifying which fields
should be used in the select clause of the right-hand-side and implicitly
set them to the left-hand-side name which assumes the same set of left-
hand-side field name is shared by the right-hand-side which is a bad
assumption
{{{#!diff
diff --git a/tests/composite_pk/models/tenant.py
b/tests/composite_pk/models/tenant.py
index 6286ed2354..c85869afa7 100644
--- a/tests/composite_pk/models/tenant.py
+++ b/tests/composite_pk/models/tenant.py
@@ -44,6 +44,7 @@ class Comment(models.Model):
related_name="comments",
)
text = models.TextField(default="", blank=True)
+ integer = models.IntegerField(default=0)
class Post(models.Model):
diff --git a/tests/composite_pk/test_filter.py
b/tests/composite_pk/test_filter.py
index fe942b9e5b..78383655a0 100644
--- a/tests/composite_pk/test_filter.py
+++ b/tests/composite_pk/test_filter.py
@@ -182,6 +182,30 @@ def test_filter_comments_by_pk_in(self):
Comment.objects.filter(pk__in=pks).order_by("pk"),
objs
)
+ def test_filter_comments_by_pk_in_subquery(self):
+ self.assertSequenceEqual(
+ Comment.objects.filter(
+ pk__in=Comment.objects.filter(pk=
self.comment_1.pk),
+ ),
+ [self.comment_1],
+ )
+ self.assertSequenceEqual(
+ Comment.objects.filter(
+
pk__in=Comment.objects.filter(pk=
self.comment_1.pk).values(
+ "tenant_id", "id"
+ ),
+ ),
+ [self.comment_1],
+ )
+ self.comment_2.integer =
self.comment_1.id
+ self.comment_2.save()
+ self.assertSequenceEqual(
+ Comment.objects.filter(
+ pk__in=Comment.objects.values("tenant_id", "integer"),
+ ),
+ [self.comment_1],
+ )
+
def test_filter_comments_by_user_and_order_by_pk_asc(self):
self.assertSequenceEqual(
Comment.objects.filter(user=self.user_1).order_by("pk"),
}}}
Allowing fields to be specified requires lifting a `QuerySet`
[
https://github.com/django/django/blob/8eca4077f60fa0705ecfd9437c9ceaeef7a3808b/django/db/models/query.py#L1967-L1970
resolving time constraint] which was entirely by-passable by passing
`queryset.query` instead as the right-hand-side.
The tuple exact lookup should also allow querysets with a single element
to be specified as right-hand-side which is currently disallowed
{{{#!diff
diff --git a/tests/composite_pk/test_filter.py
b/tests/composite_pk/test_filter.py
index fe942b9e5b..78383655a0 100644
--- a/tests/composite_pk/test_filter.py
+++ b/tests/composite_pk/test_filter.py
@@ -450,6 +474,30 @@ def test_non_outer_ref_subquery(self):
with self.assertRaisesMessage(ValueError, msg):
Comment.objects.filter(pk=pk)
+ def test_filter_comments_by_pk_exact_subquery(self):
+ self.assertSequenceEqual(
+ Comment.objects.filter(
+ pk=Comment.objects.filter(pk=
self.comment_1.pk)[:1],
+ ),
+ [self.comment_1],
+ )
+ self.assertSequenceEqual(
+ Comment.objects.filter(
+
pk__in=Comment.objects.filter(pk=
self.comment_1.pk).values(
+ "tenant_id", "id"
+ )[:1],
+ ),
+ [self.comment_1],
+ )
+ self.comment_2.integer =
self.comment_1.id
+ self.comment_2.save()
+ self.assertSequenceEqual(
+ Comment.objects.filter(
+ pk__in=Comment.objects.values("tenant_id", "integer"),
+ )[:1],
+ [self.comment_1],
+ )
+
def test_outer_ref_not_composite_pk(self):
subquery = Comment.objects.filter(pk=OuterRef("id")).values("id")
queryset = Comment.objects.filter(id=Subquery(subquery))
}}}
Lastly lifting the constraint that prevented subqueries returning more
than one column from being used as a right-hand-side required adjusting
the existing `exact` and `in` lookup logic to disallow left-hand-side and
right-hand-side with mismatching number of fields.
--
Ticket URL: <
https://code.djangoproject.com/ticket/36149>
Django <
https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.