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: kanin.kearpimy@…
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, TextField
     1from django.db.models import JSONField, Subquery, TextField
    22from django.db.models.functions import Coalesce, Lower
    33from django.test import TestCase
    44from django.utils import timezone
    class CoalesceTests(TestCase):  
    5151        self.assertQuerySetEqual(
    5252            article.order_by("title"), [lorem_ipsum.lower()], lambda a: a.headline
    5353        )
     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        )
    5462
    5563    def test_ordering(self):
    5664        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):  
    5050                ("published", models.DateTimeField(null=True, blank=True)),
    5151                ("updated", models.DateTimeField(null=True, blank=True)),
    5252                ("views", models.PositiveIntegerField(default=0)),
     53                ("metadata", models.JSONField(default=dict)),
    5354            ],
    5455        ),
    5556        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):  
    2121    published = models.DateTimeField(null=True, blank=True)
    2222    updated = models.DateTimeField(null=True, blank=True)
    2323    views = models.PositiveIntegerField(default=0)
     24    metadata = models.JSONField(default=dict)
    2425
    2526
    2627class 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 David Smith, 6 weeks ago

Triage Stage: UnreviewedAccepted

comment:2 by kanin.kearpimy@…, 3 weeks ago

Hi, I'm James (Kanin Kearpimy) from Djangonaut, 6th batch. I'm working on this issue.

comment:3 by kanin.kearpimy@…, 2 weeks ago

Duplicate with below.

Last edited 2 weeks ago by kanin.kearpimy@… (previous) (diff)

comment:4 by kanin.kearpimy@…, 2 weeks ago

Has patch: set
Owner: changed from Sarah Boyce to kanin.kearpimy@…

Patch: PR

comment:5 by Clifford Gama, 2 weeks ago

Needs tests: set

comment:6 by kanin.kearpimy@…, 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...
`

Version 1, edited 2 weeks ago by kanin.kearpimy@… (previous) (next) (diff)

comment:7 by kanin.kearpimy@…, 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 Jacob Walls, 10 days ago

Patch needs improvement: set

Left some notes about reimagining the test case to be cross-backend.

comment:9 by Jacob Walls, 8 days ago

Patch needs improvement: unset
Triage Stage: AcceptedReady for checkin

comment:10 by Jacob Walls <jacobtylerwalls@…>, 7 days ago

Resolution: fixed
Status: assignedclosed

In d7bf843:

Fixed #36906 -- Handled coalescing JSON-primitive strings and JSON values on Oracle.

Note: See TracTickets for help on using tickets.
Back to Top