Re: jsonb_set: update or upsert default?

From: Andrew Dunstan <andrew(at)dunslane(dot)net>
To: Petr Jelinek <petr(at)2ndquadrant(dot)com>, "David E(dot) Wheeler" <david(at)justatheory(dot)com>
Cc: PostgreSQL-development <pgsql-hackers(at)postgresql(dot)org>
Subject: Re: jsonb_set: update or upsert default?
Date: 2015-05-23 22:01:06
Message-ID: 5560F8A2.4020302@dunslane.net
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: 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(at)dunslane(dot)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(at)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

In response to

Browse pgsql-hackers by date

  From Date Subject
Next Message Noah Misch 2015-05-24 00:14:45 Re: RFC: Non-user-resettable SET SESSION AUTHORISATION
Previous Message Christoph Berg 2015-05-23 21:36:41 Re: fsync-pgdata-on-recovery tries to write to more files than previously