summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJacob Walls <jacobtylerwalls@gmail.com>2024-12-31 13:10:35 -0500
committerSarah Boyce <42296566+sarahboyce@users.noreply.github.com>2025-01-07 11:42:06 +0100
commit6eec703667505d87d1354323548943c8d546c5a2 (patch)
tree73a6a57401b9f4ad9f158b12aee106a2008df0a8
parent8914b571eb5f93722b9741b1da9eb69347271b11 (diff)
Fixed #36042 -- Raised ValueError when using CompositePrimaryKey as rhs.
-rw-r--r--django/db/models/expressions.py2
-rw-r--r--django/db/models/lookups.py6
-rw-r--r--tests/composite_pk/test_filter.py21
3 files changed, 28 insertions, 1 deletions
diff --git a/django/db/models/expressions.py b/django/db/models/expressions.py
index 667e9f93c6..88c5596c17 100644
--- a/django/db/models/expressions.py
+++ b/django/db/models/expressions.py
@@ -758,6 +758,8 @@ class CombinedExpression(SQLiteNumericMixin, Expression):
rhs = self.rhs.resolve_expression(
query, allow_joins, reuse, summarize, for_save
)
+ if isinstance(lhs, ColPairs) or isinstance(rhs, ColPairs):
+ raise ValueError("CompositePrimaryKey is not combinable.")
if not isinstance(self, (DurationExpression, TemporalSubtraction)):
try:
lhs_type = lhs.output_field.get_internal_type()
diff --git a/django/db/models/lookups.py b/django/db/models/lookups.py
index 734f911f83..56dbdabac1 100644
--- a/django/db/models/lookups.py
+++ b/django/db/models/lookups.py
@@ -4,7 +4,7 @@ import warnings
from django.core.exceptions import EmptyResultSet, FullResultSet
from django.db.backends.base.operations import BaseDatabaseOperations
-from django.db.models.expressions import Case, Expression, Func, Value, When
+from django.db.models.expressions import Case, ColPairs, Expression, Func, Value, When
from django.db.models.fields import (
BooleanField,
CharField,
@@ -119,6 +119,10 @@ class Lookup(Expression):
value = value.resolve_expression(compiler.query)
if hasattr(value, "as_sql"):
sql, params = compiler.compile(value)
+ if isinstance(value, ColPairs):
+ raise ValueError(
+ "CompositePrimaryKey cannot be used as a lookup value."
+ )
# Ensure expression is wrapped in parentheses to respect operator
# precedence but avoid double wrapping as it can be misinterpreted
# on some backends (e.g. subqueries on SQLite).
diff --git a/tests/composite_pk/test_filter.py b/tests/composite_pk/test_filter.py
index 7e361c5925..a99a1602a0 100644
--- a/tests/composite_pk/test_filter.py
+++ b/tests/composite_pk/test_filter.py
@@ -1,3 +1,5 @@
+from django.db.models import F, TextField
+from django.db.models.functions import Cast
from django.test import TestCase
from .models import Comment, Tenant, User
@@ -54,6 +56,20 @@ class CompositePKFilterTests(TestCase):
with self.subTest(lookup=lookup, count=count):
self.assertEqual(User.objects.filter(**lookup).count(), count)
+ def test_rhs_pk(self):
+ msg = "CompositePrimaryKey cannot be used as a lookup value."
+ with self.assertRaisesMessage(ValueError, msg):
+ Comment.objects.filter(text__gt=F("pk")).count()
+
+ def test_rhs_combinable(self):
+ msg = "CompositePrimaryKey is not combinable."
+ for expr in [F("pk") + (1, 1), (1, 1) + F("pk")]:
+ with (
+ self.subTest(expression=expr),
+ self.assertRaisesMessage(ValueError, msg),
+ ):
+ Comment.objects.filter(text__gt=expr).count()
+
def test_order_comments_by_pk_asc(self):
self.assertSequenceEqual(
Comment.objects.order_by("pk"),
@@ -410,3 +426,8 @@ class CompositePKFilterTests(TestCase):
subquery = Comment.objects.filter(id=3).only("pk")
queryset = User.objects.filter(comments__in=subquery)
self.assertSequenceEqual(queryset, (self.user_2,))
+
+ def test_cannot_cast_pk(self):
+ msg = "Casting CompositePrimaryKey is not supported."
+ with self.assertRaisesMessage(ValueError, msg):
+ Comment.objects.filter(text__gt=Cast(F("pk"), TextField())).count()