From d7bf84324fb4b0789302bd0624697ba973dd7140 Mon Sep 17 00:00:00 2001 From: Kanin Kearpimy Date: Wed, 11 Mar 2026 13:06:40 +0000 Subject: Fixed #36906 -- Handled coalescing JSON-primitive strings and JSON values on Oracle. --- django/db/models/functions/comparison.py | 7 ++++--- tests/model_fields/models.py | 1 + tests/model_fields/test_jsonfield.py | 16 +++++++++++++++- 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/django/db/models/functions/comparison.py b/django/db/models/functions/comparison.py index 8f7493f2fd..5827925e6e 100644 --- a/django/db/models/functions/comparison.py +++ b/django/db/models/functions/comparison.py @@ -86,9 +86,10 @@ class Coalesce(Func): return None def as_oracle(self, compiler, connection, **extra_context): - # Oracle prohibits mixing TextField (NCLOB) and CharField (NVARCHAR2), - # so convert all fields to NCLOB when that type is expected. - if self.output_field.get_internal_type() == "TextField": + # Oracle prohibits mixing TextField, JSONField (NCLOB) and CharField + # (NVARCHAR2), so convert all fields to NCLOB when that type is + # expected. + if self.output_field.get_internal_type() in ("TextField", "JSONField"): clone = self.copy() clone.set_source_expressions( [ diff --git a/tests/model_fields/models.py b/tests/model_fields/models.py index a594b89adb..c1e356bb53 100644 --- a/tests/model_fields/models.py +++ b/tests/model_fields/models.py @@ -452,6 +452,7 @@ class JSONNullDefaultModel(models.Model): class RelatedJSONModel(models.Model): value = models.JSONField() json_model = models.ForeignKey(NullableJSONModel, models.CASCADE) + summary = models.CharField(max_length=100, null=True, blank=True) class Meta: required_db_features = {"supports_json_field"} diff --git a/tests/model_fields/test_jsonfield.py b/tests/model_fields/test_jsonfield.py index 1afeef31eb..7b07a48a1e 100644 --- a/tests/model_fields/test_jsonfield.py +++ b/tests/model_fields/test_jsonfield.py @@ -40,7 +40,7 @@ from django.db.models.fields.json import ( KeyTransformFactory, KeyTransformTextLookupMixin, ) -from django.db.models.functions import Cast +from django.db.models.functions import Cast, Coalesce from django.test import ( SimpleTestCase, TestCase, @@ -1290,6 +1290,20 @@ class TestQuerying(TestCase): ) self.assertQuerySetEqual(qs, all_objects) + @skipUnlessDBFeature("supports_primitives_in_json_field") + def test_json_type_casting_with_coalesce(self): + RelatedJSONModel.objects.create( + summary='"This is valid JSON primitive."', + value={"text": "test"}, + json_model=self.objs[4], + ) + result = RelatedJSONModel.objects.annotate( + coalesced_value=Coalesce( + Cast("summary", JSONField()), "value", output_field=JSONField() + ) + ).first() + self.assertEqual(result.coalesced_value, "This is valid JSON primitive.") + @skipUnlessDBFeature("supports_primitives_in_json_field") class JSONNullTests(TestCase): -- cgit v1.3