瀏覽代碼

Fixed #36042 -- Raised ValueError when using CompositePrimaryKey as rhs.

Jacob Walls 2 月之前
父節點
當前提交
6eec703667
共有 3 個文件被更改,包括 28 次插入1 次删除
  1. 2 0
      django/db/models/expressions.py
  2. 5 1
      django/db/models/lookups.py
  3. 21 0
      tests/composite_pk/test_filter.py

+ 2 - 0
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()

+ 5 - 1
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).

+ 21 - 0
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()