mirror of
https://github.com/django/django.git
synced 2025-03-06 15:32:33 +00:00
Fixed #34060 -- Fixed migrations crash when adding check constraints with JSONField __exact lookup on Oracle.
This commit is contained in:
parent
22285d366c
commit
c991602ce5
@ -347,9 +347,10 @@ END;
|
|||||||
def lookup_cast(self, lookup_type, internal_type=None):
|
def lookup_cast(self, lookup_type, internal_type=None):
|
||||||
if lookup_type in ("iexact", "icontains", "istartswith", "iendswith"):
|
if lookup_type in ("iexact", "icontains", "istartswith", "iendswith"):
|
||||||
return "UPPER(%s)"
|
return "UPPER(%s)"
|
||||||
if (
|
if lookup_type != "isnull" and internal_type in (
|
||||||
lookup_type != "isnull" and internal_type in ("BinaryField", "TextField")
|
"BinaryField",
|
||||||
) or (lookup_type == "exact" and internal_type == "JSONField"):
|
"TextField",
|
||||||
|
):
|
||||||
return "DBMS_LOB.SUBSTR(%s)"
|
return "DBMS_LOB.SUBSTR(%s)"
|
||||||
return "%s"
|
return "%s"
|
||||||
|
|
||||||
|
@ -106,6 +106,13 @@ class DatabaseFeatures(BaseDatabaseFeatures):
|
|||||||
"test_group_by_nested_expression_with_params",
|
"test_group_by_nested_expression_with_params",
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
if not is_psycopg3:
|
||||||
|
expected_failures.update(
|
||||||
|
{
|
||||||
|
"constraints.tests.CheckConstraintTests."
|
||||||
|
"test_validate_jsonfield_exact",
|
||||||
|
}
|
||||||
|
)
|
||||||
return expected_failures
|
return expected_failures
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
|
@ -310,6 +310,11 @@ class JSONExact(lookups.Exact):
|
|||||||
rhs %= tuple(func)
|
rhs %= tuple(func)
|
||||||
return rhs, rhs_params
|
return rhs, rhs_params
|
||||||
|
|
||||||
|
def as_oracle(self, compiler, connection):
|
||||||
|
lhs, lhs_params = self.process_lhs(compiler, connection)
|
||||||
|
rhs, rhs_params = self.process_rhs(compiler, connection)
|
||||||
|
return f"JSON_EQUAL({lhs}, {rhs})", (*lhs_params, *rhs_params)
|
||||||
|
|
||||||
|
|
||||||
class JSONIContains(CaseInsensitiveMixin, lookups.IContains):
|
class JSONIContains(CaseInsensitiveMixin, lookups.IContains):
|
||||||
pass
|
pass
|
||||||
|
@ -365,6 +365,20 @@ class CheckConstraintTests(TestCase):
|
|||||||
constraint_with_pk.validate(ChildModel, ChildModel(id=1, age=1))
|
constraint_with_pk.validate(ChildModel, ChildModel(id=1, age=1))
|
||||||
constraint_with_pk.validate(ChildModel, ChildModel(pk=1, age=1), exclude={"pk"})
|
constraint_with_pk.validate(ChildModel, ChildModel(pk=1, age=1), exclude={"pk"})
|
||||||
|
|
||||||
|
@skipUnlessDBFeature("supports_json_field")
|
||||||
|
def test_validate_jsonfield_exact(self):
|
||||||
|
data = {"release": "5.0.2", "version": "stable"}
|
||||||
|
json_exact_constraint = models.CheckConstraint(
|
||||||
|
check=models.Q(data__version="stable"),
|
||||||
|
name="only_stable_version",
|
||||||
|
)
|
||||||
|
json_exact_constraint.validate(JSONFieldModel, JSONFieldModel(data=data))
|
||||||
|
|
||||||
|
data = {"release": "5.0.2", "version": "not stable"}
|
||||||
|
msg = f"Constraint “{json_exact_constraint.name}” is violated."
|
||||||
|
with self.assertRaisesMessage(ValidationError, msg):
|
||||||
|
json_exact_constraint.validate(JSONFieldModel, JSONFieldModel(data=data))
|
||||||
|
|
||||||
|
|
||||||
class UniqueConstraintTests(TestCase):
|
class UniqueConstraintTests(TestCase):
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -2803,6 +2803,40 @@ class SchemaTests(TransactionTestCase):
|
|||||||
DurationModel.objects.create(duration=datetime.timedelta(minutes=4))
|
DurationModel.objects.create(duration=datetime.timedelta(minutes=4))
|
||||||
DurationModel.objects.create(duration=datetime.timedelta(minutes=10))
|
DurationModel.objects.create(duration=datetime.timedelta(minutes=10))
|
||||||
|
|
||||||
|
@skipUnlessDBFeature(
|
||||||
|
"supports_column_check_constraints",
|
||||||
|
"can_introspect_check_constraints",
|
||||||
|
"supports_json_field",
|
||||||
|
)
|
||||||
|
@isolate_apps("schema")
|
||||||
|
def test_check_constraint_exact_jsonfield(self):
|
||||||
|
class JSONConstraintModel(Model):
|
||||||
|
data = JSONField()
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
app_label = "schema"
|
||||||
|
|
||||||
|
with connection.schema_editor() as editor:
|
||||||
|
editor.create_model(JSONConstraintModel)
|
||||||
|
self.isolated_local_models = [JSONConstraintModel]
|
||||||
|
constraint_name = "check_only_stable_version"
|
||||||
|
constraint = CheckConstraint(
|
||||||
|
check=Q(data__version="stable"),
|
||||||
|
name=constraint_name,
|
||||||
|
)
|
||||||
|
JSONConstraintModel._meta.constraints = [constraint]
|
||||||
|
with connection.schema_editor() as editor:
|
||||||
|
editor.add_constraint(JSONConstraintModel, constraint)
|
||||||
|
constraints = self.get_constraints(JSONConstraintModel._meta.db_table)
|
||||||
|
self.assertIn(constraint_name, constraints)
|
||||||
|
with self.assertRaises(IntegrityError), atomic():
|
||||||
|
JSONConstraintModel.objects.create(
|
||||||
|
data={"release": "5.0.2dev", "version": "dev"}
|
||||||
|
)
|
||||||
|
JSONConstraintModel.objects.create(
|
||||||
|
data={"release": "5.0.3", "version": "stable"}
|
||||||
|
)
|
||||||
|
|
||||||
@skipUnlessDBFeature(
|
@skipUnlessDBFeature(
|
||||||
"supports_column_check_constraints", "can_introspect_check_constraints"
|
"supports_column_check_constraints", "can_introspect_check_constraints"
|
||||||
)
|
)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user