Re: jsonb_set: update or upsert default? - Mailing list pgsql-hackers

From Andrew Dunstan
Subject Re: jsonb_set: update or upsert default?
Date
Msg-id 5560F8A2.4020302@dunslane.net
Whole thread Raw
In response to Re: jsonb_set: update or upsert default?  (Petr Jelinek <petr@2ndquadrant.com>)
List pgsql-hackers
On 05/23/2015 04:03 PM, Petr Jelinek wrote:
> On 23/05/15 17:59, David E. Wheeler wrote:
>> On May 22, 2015, at 7:22 PM, Andrew Dunstan <andrew@dunslane.net> wrote:
>>
>>> The proposed flag for jsonb_set (the renamed jsonb_replace) in the
>>> patch I recently published is set to false, meaning that the default
>>> behaviour is to require all elements of the path including the last
>>> to be present. What that does is effectively UPDATE for jsonb. If
>>> the flag is true, then the last element can be absent, in which case
>>> it's created, so this is basically UPSERT for jsonb. The question is
>>> which should be the default. We got into the weeds on this with
>>> suggestions of throwing errors on missing paths, but that's going
>>> nowhere, and I want to get discussion back onto the topic of what
>>> should be the default.
>>
>> Here’s JavaScript in Chrome, FWIW:
>>
>> var f = {}
>> f["foo"][0] = “bar"
>> Uncaught TypeError: Cannot set property '0' of undefined
>>      at <anonymous>:2:13
>>      at Object.InjectedScript._evaluateOn (<anonymous>:895:140)
>>      at Object.InjectedScript._evaluateAndWrap (<anonymous>:828:34)
>>      at Object.InjectedScript.evaluate (<anonymous>:694:21)
>>
>
> As I understand it, that's not really the same as what Andrew says.
> The real example of that is
> > var f = {}
> > f["foo"] = “bar"
> > f
> { foo: 'bar' }


Yeah, more or less.

>
> which works fine in JavaScript and most other dynamic languages like
> Python or Perl. So my opinion is that default should be true here.


OK, although Perl at least will autovivify the whole path:
   [andrew@emma ~]$ perl -e 'my %x; $x{foo}{bar}{baz} = 1; use   Data::Dumper; print Dumper(\%x);'   $VAR1 = {
   'foo' => {                         'bar' => {                                    'baz' => 1
       }                       }            }; 

But since, as David's example shows, JS doesn't do that we seem to be on
solid ground not doing it either.

>
> Another thing I noticed is that while following looks as expected:
> # select jsonb_set('{"baz":1}'::jsonb, '{foo}', '"bar"', true);
>         jsonb_set
> --------------------------
>  {"baz": 1, "foo": "bar"}
> (1 row)
>
> If I use empty jsonb object it does not work anymore:
> # select jsonb_set('{}', '{foo}', '"bar"', true);
>  jsonb_set
> -----------
>  {}
> (1 row)
>
>


Oh, that looks like a bug. Will check. Thanks.

cheers

andrew



pgsql-hackers by date:

Previous
From: Christoph Berg
Date:
Subject: Re: fsync-pgdata-on-recovery tries to write to more files than previously
Next
From: Noah Misch
Date:
Subject: Re: RFC: Non-user-resettable SET SESSION AUTHORISATION