mirror of https://github.com/django/django.git
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 5c23d9f0c3
.
Thanks Alexandre Collet for the report.
This commit is contained in:
parent
2b582387d5
commit
3434dbd39d
|
@ -607,6 +607,11 @@ class IsNull(BuiltinLookup):
|
|||
raise ValueError(
|
||||
"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)
|
||||
if self.rhs:
|
||||
return "%s IS NULL" % sql, params
|
||||
|
|
|
@ -9,4 +9,6 @@ Django 4.2.5 fixes several bugs in 4.2.4.
|
|||
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):
|
||||
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 (
|
||||
ChildModel,
|
||||
ChildUniqueConstraintProduct,
|
||||
JSONFieldModel,
|
||||
Product,
|
||||
UniqueConstraintConditionProduct,
|
||||
UniqueConstraintDeferrable,
|
||||
|
@ -332,6 +333,25 @@ class CheckConstraintTests(TestCase):
|
|||
)
|
||||
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):
|
||||
@classmethod
|
||||
|
|
Loading…
Reference in New Issue