mirror of
https://github.com/django/django.git
synced 2025-06-05 11:39:13 +00:00
Fixed #34754 -- Fixed JSONField check constraints validation on NULL values.
The __isnull lookup of JSONField must special case Value(None, JSONField()) left-hand-side in order to be coherent with its convoluted null handling. Since psycopg>=3 offers no way to pass a NULL::jsonb the issue is resolved by optimizing IsNull(Value(None), True | False) to True | False. Regression in 5c23d9f0c32f166c81ecb6f3f01d5077a6084318. Thanks Alexandre Collet for the report.
This commit is contained in:
parent
2b582387d5
commit
3434dbd39d
@ -607,6 +607,11 @@ class IsNull(BuiltinLookup):
|
|||||||
raise ValueError(
|
raise ValueError(
|
||||||
"The QuerySet value for an isnull lookup must be True or False."
|
"The QuerySet value for an isnull lookup must be True or False."
|
||||||
)
|
)
|
||||||
|
if isinstance(self.lhs, Value) and self.lhs.value is None:
|
||||||
|
if self.rhs:
|
||||||
|
raise FullResultSet
|
||||||
|
else:
|
||||||
|
raise EmptyResultSet
|
||||||
sql, params = self.process_lhs(compiler, connection)
|
sql, params = self.process_lhs(compiler, connection)
|
||||||
if self.rhs:
|
if self.rhs:
|
||||||
return "%s IS NULL" % sql, params
|
return "%s IS NULL" % sql, params
|
||||||
|
@ -9,4 +9,6 @@ Django 4.2.5 fixes several bugs in 4.2.4.
|
|||||||
Bugfixes
|
Bugfixes
|
||||||
========
|
========
|
||||||
|
|
||||||
* ...
|
* Fixed a regression in Django 4.2 that caused an incorrect validation of
|
||||||
|
``CheckConstraints`` on ``__isnull`` lookups against ``JSONField``
|
||||||
|
(:ticket:`34754`).
|
||||||
|
@ -121,3 +121,10 @@ class AbstractModel(models.Model):
|
|||||||
|
|
||||||
class ChildModel(AbstractModel):
|
class ChildModel(AbstractModel):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class JSONFieldModel(models.Model):
|
||||||
|
data = models.JSONField(null=True)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
required_db_features = {"supports_json_field"}
|
||||||
|
@ -13,6 +13,7 @@ from django.utils.deprecation import RemovedInDjango60Warning
|
|||||||
from .models import (
|
from .models import (
|
||||||
ChildModel,
|
ChildModel,
|
||||||
ChildUniqueConstraintProduct,
|
ChildUniqueConstraintProduct,
|
||||||
|
JSONFieldModel,
|
||||||
Product,
|
Product,
|
||||||
UniqueConstraintConditionProduct,
|
UniqueConstraintConditionProduct,
|
||||||
UniqueConstraintDeferrable,
|
UniqueConstraintDeferrable,
|
||||||
@ -332,6 +333,25 @@ class CheckConstraintTests(TestCase):
|
|||||||
)
|
)
|
||||||
constraint.validate(Product, Product())
|
constraint.validate(Product, Product())
|
||||||
|
|
||||||
|
@skipUnlessDBFeature("supports_json_field")
|
||||||
|
def test_validate_nullable_jsonfield(self):
|
||||||
|
is_null_constraint = models.CheckConstraint(
|
||||||
|
check=models.Q(data__isnull=True),
|
||||||
|
name="nullable_data",
|
||||||
|
)
|
||||||
|
is_not_null_constraint = models.CheckConstraint(
|
||||||
|
check=models.Q(data__isnull=False),
|
||||||
|
name="nullable_data",
|
||||||
|
)
|
||||||
|
is_null_constraint.validate(JSONFieldModel, JSONFieldModel(data=None))
|
||||||
|
msg = f"Constraint “{is_null_constraint.name}” is violated."
|
||||||
|
with self.assertRaisesMessage(ValidationError, msg):
|
||||||
|
is_null_constraint.validate(JSONFieldModel, JSONFieldModel(data={}))
|
||||||
|
msg = f"Constraint “{is_not_null_constraint.name}” is violated."
|
||||||
|
with self.assertRaisesMessage(ValidationError, msg):
|
||||||
|
is_not_null_constraint.validate(JSONFieldModel, JSONFieldModel(data=None))
|
||||||
|
is_not_null_constraint.validate(JSONFieldModel, JSONFieldModel(data={}))
|
||||||
|
|
||||||
|
|
||||||
class UniqueConstraintTests(TestCase):
|
class UniqueConstraintTests(TestCase):
|
||||||
@classmethod
|
@classmethod
|
||||||
|
Loading…
x
Reference in New Issue
Block a user