#36453: 5.2.3 introduces a regression when using `Value(None,
output_field=JSONField()` in a `When` clause.
-------------------------------------+-------------------------------------
     Reporter:  Thomas               |                    Owner:  (none)
         Type:  Bug                  |                   Status:  new
    Component:  Database layer       |                  Version:  5.2
  (models, ORM)                      |
     Severity:  Normal               |               Resolution:
     Keywords:                       |             Triage Stage:
                                     |  Unreviewed
    Has patch:  0                    |      Needs documentation:  0
  Needs tests:  0                    |  Patch needs improvement:  0
Easy pickings:  0                    |                    UI/UX:  0
-------------------------------------+-------------------------------------
Description changed by Thomas:

Old description:

> We've tried to upgrade to 5.2.3 and several of our tests started failing.
> We've pinpointed the problem to one query which uses `Value(None,
> output_field=JSONField()` in a `When` clause. Here's a minimal
> reproducible example (with a `WHERE` clause too, to highlight the
> difference in behavior):
>
> {{{
> from django.db import connection
> from django.db.models import (
>     BigIntegerField,
>     Case,
>     F,
>     JSONField,
>     Model,
>     Value,
>     When,
> )
> from django.db.models.functions import Cast
>

> class Foo(Model):
>     bar = BigIntegerField(blank=True, null=True)
>     json_field = JSONField(blank=True, null=True)
>

> if __name__ == '__main__':
>     Foo.objects.filter(
>         json_field__key_1=Value(None, output_field=JSONField())
>     ).update(
>         bar=Case(
>             When(
>                 json_field__key_2=Value(None, output_field=JSONField()),
>                 then=None
>             ),
>             default=Cast(F('json_field__key_2'), BigIntegerField()),
>             output_field=BigIntegerField(),
>         ),
>     )
>
>     print(connection.queries[-1]['sql'])
> }}}
>
> We ran this code with 5.2.2 (with this version our test suite passes) and
> 5.2.3 (with this version our test suite fails) and got this:
> {{{
> -- Generated with Django 5.2.2
> UPDATE "polls_foo"
> SET "bar" = CASE WHEN (
>         ("polls_foo"."json_field" -> 'key_2') = 'null'::jsonb  -- JSON
> "null"
>     )
>     THEN NULL
>     ELSE (("polls_foo"."json_field" -> 'key_2'))::bigint
>     END
> WHERE ("polls_foo"."json_field" -> 'key_1') = 'null'::jsonb;
>
> -- Generated with Django 5.2.3
> UPDATE "polls_foo"
> SET "bar" = CASE WHEN (
>         ("polls_foo"."json_field" -> 'key_2') = NULL  -- SQL NULL
>     )
>     THEN NULL
>     ELSE (("polls_foo"."json_field" -> 'key_2'))::bigint
>     END
> WHERE ("polls_foo"."json_field" -> 'key_1') = 'null'::jsonb;
> }}}
>
> Notice how the `WHEN` clause differs, but the `WHERE` clause stays the
> same, despite both using the same `Value(None, output_field=JSONField())`
> syntax.

New description:

 We've tried to upgrade to 5.2.3 and several of our tests started failing.
 We've pinpointed the problem to one query which uses `Value(None,
 output_field=JSONField()` in a `When` clause. Here's a minimal
 reproducible example (with a `WHERE` clause too, to highlight the
 difference in behavior):

 {{{
 from django.db import connection
 from django.db.models import (
     BigIntegerField,
     Case,
     F,
     JSONField,
     Model,
     Value,
     When,
 )
 from django.db.models.functions import Cast


 class Foo(Model):
     bar = BigIntegerField(blank=True, null=True)
     json_field = JSONField(blank=True, null=True)


 if __name__ == '__main__':
     Foo.objects.filter(
         json_field__key_1=Value(None, output_field=JSONField())
     ).update(
         bar=Case(
             When(
                 json_field__key_2=Value(None, output_field=JSONField()),
                 then=None
             ),
             default=Cast(F('json_field__key_2'), BigIntegerField()),
             output_field=BigIntegerField(),
         ),
     )

     print(connection.queries[-1]['sql'])
 }}}

 We ran this code with 5.2.2 (with this version our test suite passes) and
 5.2.3 (with this version our test suite fails) and got this:
 {{{
 -- Generated with Django 5.2.2
 UPDATE "polls_foo"
 SET "bar" = CASE WHEN (
         ("polls_foo"."json_field" -> 'key_2') = 'null'::jsonb  -- JSON
 "null"
     )
     THEN NULL
     ELSE (("polls_foo"."json_field" -> 'key_2'))::bigint
     END
 WHERE ("polls_foo"."json_field" -> 'key_1') = 'null'::jsonb;

 -- Generated with Django 5.2.3
 UPDATE "polls_foo"
 SET "bar" = CASE WHEN (
         ("polls_foo"."json_field" -> 'key_2') = NULL  -- SQL NULL
     )
     THEN NULL
     ELSE (("polls_foo"."json_field" -> 'key_2'))::bigint
     END
 WHERE ("polls_foo"."json_field" -> 'key_1') = 'null'::jsonb;
 }}}

 Notice how the `WHEN` clause differs, but the `WHERE` clause stays the
 same, despite both using the same `Value(None, output_field=JSONField())`
 syntax.

 Edit: If that makes any difference, we're using PostgreSQL as a backend.

--
-- 
Ticket URL: <https://code.djangoproject.com/ticket/36453#comment:1>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion visit 
https://groups.google.com/d/msgid/django-updates/010701975be1de5b-566e2bd1-1d68-425d-b5c7-6c9216cee2e4-000000%40eu-central-1.amazonses.com.

Reply via email to