Re: BUG #15140: Incorrect jsonb_set behavoir

Lists: pgsql-bugs
From: PG Bug reporting form <noreply(at)postgresql(dot)org>
To: pgsql-bugs(at)lists(dot)postgresql(dot)org
Cc: i(dot)panchenko(at)postgrespro(dot)ru
Subject: BUG #15140: Incorrect jsonb_set behavoir
Date: 2018-04-02 10:36:45
Message-ID: 152266540508.1442.16790414733320933622@wrigleys.postgresql.org
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-bugs

The following bug has been logged on the website:

Bug reference: 15140
Logged by: Ivan Panchenko
Email address: i(dot)panchenko(at)postgrespro(dot)ru
PostgreSQL version: 10.3
Operating system: any
Description:

First. Impossible to create a nested structure for a path with more than one
new keys.

postgres => select jsonb_set('{}'::jsonb, array['x', 'y'],
to_jsonb(1::text), true);
jsonb_set
-----------
{}
(1 строка)

Expected {"x": { "y" : "1" }}

Second. Setting a NULL value nullifies the whole JSON

postgres=> select jsonb_set('{}'::jsonb, array['x'], null, true);
jsonb_insert
--------------

(1 строка)

Expected { "x" : null }


From: Dmitry Dolgov <9erthalion6(at)gmail(dot)com>
To: "Ivan E(dot) Panchenko" <i(dot)panchenko(at)postgrespro(dot)ru>, pgsql-bugs(at)lists(dot)postgresql(dot)org
Subject: Re: BUG #15140: Incorrect jsonb_set behavoir
Date: 2018-04-02 12:04:12
Message-ID: CA+q6zcWorxezaaN9RQgURkmiyjer3nT8_zO2Sp6700FaROVk5Q@mail.gmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-bugs

> On 2 April 2018 at 12:36, PG Bug reporting form <noreply(at)postgresql(dot)org> wrote:
> The following bug has been logged on the website:
>
> Bug reference: 15140
> Logged by: Ivan Panchenko
> Email address: i(dot)panchenko(at)postgrespro(dot)ru
> PostgreSQL version: 10.3
> Operating system: any
> Description:
>
> First. Impossible to create a nested structure for a path with more than one
> new keys.
>
> postgres => select jsonb_set('{}'::jsonb, array['x', 'y'],
> to_jsonb(1::text), true);
> jsonb_set
> -----------
> {}
> (1 строка)
>
> Expected {"x": { "y" : "1" }}
>
> Second. Setting a NULL value nullifies the whole JSON
>
> postgres=> select jsonb_set('{}'::jsonb, array['x'], null, true);
> jsonb_insert
> --------------
>
> (1 строка)
>
> Expected { "x" : null }

As far as I remember, these are not really bugs, but documented behavior.

About the first one, here is [1]:

All the items of the path parameter of jsonb_set as well as jsonb_insert
except the last item must be present in the target. If create_missing is
false, all items of the path parameter of jsonb_set must be present. If
these conditions are not met the target is returned unchanged.

Although I agree this can be confusing, and we may want to change this.

About the second one, `jsonb_set` is defined as a strict function, which means
`null` arguments will produce null as a result. To avoid this you can do:

=# select jsonb_set('{}'::jsonb, array['x'], 'null', true);
jsonb_set
-------------
{"x": null}
(1 row)

1: /docs/devel/static/functions-json.html


From: "Ivan E(dot) Panchenko" <i(dot)panchenko(at)postgrespro(dot)ru>
To: Dmitry Dolgov <9erthalion6(at)gmail(dot)com>, pgsql-bugs(at)lists(dot)postgresql(dot)org
Subject: Re: BUG #15140: Incorrect jsonb_set behavoir
Date: 2018-04-02 14:58:15
Message-ID: 3ab7ce91-9d9e-8b82-e77f-73d2da52c17e@postgrespro.ru
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-bugs

Hi,

02.04.2018 15:04, Dmitry Dolgov пишет:
>> On 2 April 2018 at 12:36, PG Bug reporting form <noreply(at)postgresql(dot)org> wrote:
>> The following bug has been logged on the website:
>>
>> Bug reference: 15140
>> Logged by: Ivan Panchenko
>> Email address: i(dot)panchenko(at)postgrespro(dot)ru
>> PostgreSQL version: 10.3
>> Operating system: any
>> Description:
>>
>> First. Impossible to create a nested structure for a path with more than one
>> new keys.
>>
>> postgres => select jsonb_set('{}'::jsonb, array['x', 'y'],
>> to_jsonb(1::text), true);
>> jsonb_set
>> -----------
>> {}
>> (1 строка)
>>
>> Expected {"x": { "y" : "1" }}
>>
>> Second. Setting a NULL value nullifies the whole JSON
>>
>> postgres=> select jsonb_set('{}'::jsonb, array['x'], null, true);
>> jsonb_insert
>> --------------
>>
>> (1 строка)
>>
>> Expected { "x" : null }
> As far as I remember, these are not really bugs, but documented behavior.
>
> About the first one, here is [1]:
>
> All the items of the path parameter of jsonb_set as well as jsonb_insert
> except the last item must be present in the target. If create_missing is
> false, all items of the path parameter of jsonb_set must be present. If
> these conditions are not met the target is returned unchanged.
>
> Although I agree this can be confusing, and we may want to change this.
Yes, I think it would be good.

Now I see it in the documentation, but unfortunately, it  is  a separate
note, which is not referenced from the main jsonb_set description which 
says,

        ...with /|new_value|/ added if /|create_missing|/ is true (
default is |true|) and the item designated by /|path|/ does not exist.

> About the second one, `jsonb_set` is defined as a strict function, which means
> `null` arguments will produce null as a result. To avoid this you can do:
>
> =# select jsonb_set('{}'::jsonb, array['x'], 'null', true);
> jsonb_set
> -------------
> {"x": null}
> (1 row)
>
> 1: /docs/devel/static/functions-json.html
Thanks for the workaround.  Nevertheless, this behavior looks
counter-intuitive, and I would vote for removing strictness from this
function.

Regards,
Ivan


From: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
To: "Ivan E(dot) Panchenko" <i(dot)panchenko(at)postgrespro(dot)ru>
Cc: Dmitry Dolgov <9erthalion6(at)gmail(dot)com>, pgsql-bugs(at)lists(dot)postgresql(dot)org
Subject: Re: BUG #15140: Incorrect jsonb_set behavoir
Date: 2018-04-02 15:02:49
Message-ID: 2394.1522681369@sss.pgh.pa.us
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-bugs

"Ivan E. Panchenko" <i(dot)panchenko(at)postgrespro(dot)ru> writes:
> Thanks for the workaround.  Nevertheless, this behavior looks
> counter-intuitive, and I would vote for removing strictness from this
> function.

That would amount to assuming that SQL NULL and JSON 'null' are
interchangeable, which isn't the case elsewhere, and I'm not sure
we want it to be the case here. You can get the behavior you're
looking for with jsonb_set(..., COALESCE(fieldvalue, 'null')).

regards, tom lane