Opened 6 weeks ago
Closed 7 days ago
#36906 closed Bug (fixed)
Oracle guard for coalescing text & varchar doesn't fathom JSONField
| Reported by: | Jacob Walls | Owned by: | |
|---|---|---|---|
| Component: | Database layer (models, ORM) | Version: | dev |
| Severity: | Normal | Keywords: | |
| Cc: | Triage Stage: | Ready for checkin | |
| Has patch: | yes | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description
Coalesce has an as_oracle() method to make sure that varchar and NCLOB (text) fields are not mixed. JSONField is also implemented as an NCLOB type, so it needs to be included in the check, too.
Discovered in https://github.com/django/django/pull/20009#discussion_r2500562079.
Rough test for demonstration purposes -- a little more realism would be nice.
-
tests/db_functions/comparison/test_coalesce.py
diff --git a/tests/db_functions/comparison/test_coalesce.py b/tests/db_functions/comparison/test_coalesce.py index b08ae742df..839954f73c 100644
a b 1 from django.db.models import Subquery, TextField1 from django.db.models import JSONField, Subquery, TextField 2 2 from django.db.models.functions import Coalesce, Lower 3 3 from django.test import TestCase 4 4 from django.utils import timezone … … class CoalesceTests(TestCase): 51 51 self.assertQuerySetEqual( 52 52 article.order_by("title"), [lorem_ipsum.lower()], lambda a: a.headline 53 53 ) 54 # mixed JSON and Char 55 article = Article.objects.annotate( 56 # fix this to be more realistic? 57 summary_or_metadata=Coalesce("summary", "metadata", output_field=JSONField()), 58 ) 59 self.assertQuerySetEqual( 60 article.order_by("title"), [{}], lambda a: a.summary_or_metadata 61 ) 54 62 55 63 def test_ordering(self): 56 64 Author.objects.create(name="John Smith", alias="smithj") -
tests/db_functions/migrations/0002_create_test_models.py
diff --git a/tests/db_functions/migrations/0002_create_test_models.py b/tests/db_functions/migrations/0002_create_test_models.py index 2fa924cbe0..7c57a1eee7 100644
a b class Migration(migrations.Migration): 50 50 ("published", models.DateTimeField(null=True, blank=True)), 51 51 ("updated", models.DateTimeField(null=True, blank=True)), 52 52 ("views", models.PositiveIntegerField(default=0)), 53 ("metadata", models.JSONField(default=dict)), 53 54 ], 54 55 ), 55 56 migrations.CreateModel( -
tests/db_functions/models.py
diff --git a/tests/db_functions/models.py b/tests/db_functions/models.py index 45a5a027f4..7fb6200fb5 100644
a b class Article(models.Model): 21 21 published = models.DateTimeField(null=True, blank=True) 22 22 updated = models.DateTimeField(null=True, blank=True) 23 23 views = models.PositiveIntegerField(default=0) 24 metadata = models.JSONField(default=dict) 24 25 25 26 26 27 class Fan(models.Model):
django.db.utils.DatabaseError: ORA-00932: expression ("DB_FUNCTIONS_ARTICLE"."METADATA") is of data type NCLOB, which is incompatible with expected data type NCHAR Help: https://docs.oracle.com/error-help/db/ora-00932/
Change History (10)
comment:1 by , 6 weeks ago
| Triage Stage: | Unreviewed → Accepted |
|---|
comment:2 by , 3 weeks ago
comment:5 by , 2 weeks ago
| Needs tests: | set |
|---|
comment:6 by , 2 weeks ago
Unexpectedly after writing test, I found out postgres does throw similar error. However, my implementation doesn't negatively affect oracle, mysql, mariadb, sqlite (I ran db test in my local and pipeline, no evidence of failure regarding those DBs).
File "/django/source/django/db/backends/utils.py", line 92, in _execute_with_wrappers
return executor(sql, params, many, context)
File "/django/source/django/db/backends/utils.py", line 100, in _execute
with self.db.wrap_database_errors:
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/django/source/django/db/utils.py", line 94, in __exit__
raise dj_exc_value.with_traceback(traceback) from exc_value
File "/django/source/django/db/backends/utils.py", line 105, in _execute
return self.cursor.execute(sql, params)
~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^
File "/usr/local/lib/python3.14/site-packages/psycopg/cursor.py", line 117, in execute
raise ex.with_traceback(None)
django.db.utils.ProgrammingError: COALESCE types character varying and jsonb cannot be matched
LINE 1: ...data", COALESCE("db_functions_article"."summary", "db_functi...
comment:7 by , 12 days ago
| Needs tests: | unset |
|---|
Hi, I added test and it all pass on oracle. So, I unflagged this "need test" for this issue.
comment:8 by , 10 days ago
| Patch needs improvement: | set |
|---|
Left some notes about reimagining the test case to be cross-backend.
comment:9 by , 8 days ago
| Patch needs improvement: | unset |
|---|---|
| Triage Stage: | Accepted → Ready for checkin |
Hi, I'm James (Kanin Kearpimy) from Djangonaut, 6th batch. I'm working on this issue.