Re: json accessors - Mailing list pgsql-hackers

From Andrew Dunstan
Subject Re: json accessors
Date
Msg-id 50B8C4E9.4090900@dunslane.net
Whole thread Raw
In response to Re: json accessors  (Merlin Moncure <mmoncure@gmail.com>)
Responses Re: json accessors  (Merlin Moncure <mmoncure@gmail.com>)
Re: json accessors  (Hannu Krosing <hannu@2ndQuadrant.com>)
List pgsql-hackers
On 11/29/2012 06:34 PM, Merlin Moncure wrote:
> On Thu, Nov 29, 2012 at 4:14 PM, Andrew Dunstan <andrew@dunslane.net> wrote:
>> There are many things wrong with this. First, converting to hstore so you
>> can call populate_record is quite horrible and ugly and inefficient. And
>> it's dependent on having hstore loaded - you can't have an hstore_to_jon in
>> core because hstore itself isn't in core. If you want a populate_record that
>> takes data from json we should have one coded direct. I'm happy to add it to
>> the list as long as everyone understands the limitations. Given a function
>> to unnest the json array, which I already suggested upthread, you could do
>> what you suggested above much more elegantly and directly.
> I wasn't suggesting you added the hstore stuff and I understand
> perfectly well the awkwardness of the hstore route.  That said, this
> is how people are going to use your api so it doesn't hurt to go
> through the motions; I'm just feeling out how code in the wild would
> shape up.
>
> Anyways, my example was busted since you'd need an extra step to move
> the set returning output from the json array unnest() into a
> 'populate_record' type function call.
>
> So, AIUI I think you're proposing (i'm assuming optional quotes)
> following my example above:
>
> INSERT INTO foo(a,b)
> SELECT
>    json_get_as_text(v, 'a')::int,
>    json_get_as_text(v, 'b')::int
> FROM
>    json_each(<document>) v;  /* gives you array of json (a,b) records  */
>
> a hypothetical 'json_to_record (cribbing usage from populate_record)'
> variant might look like (please note, I'm not saying 'write this now',
> just feeling it out)::
>
> INSERT INTO foo(a,b)
> SELECT  r.*
> FROM
>    json_each(<document>) v,
> LATERAL
>    json_to_record(null::foo, v) r;
>
> you're right: that's pretty clean.
>
> An json_object_each(json), => key, value couldn't hurt either -- this
> would handle those oddball cases of really wide objects that you
> occasionally see in json.  Plus as_text variants of both each and
> object_each.  If you're buying json_object_each, I think you can scrap
> json_object_keys().
>


OK, so based on this discussion, I'm thinking of the following:
 * keep the original functions and operators. json_keys is still   required for the case where the json is not flat. *
json_each(json)=> setof (text, text)   errors if the json is not a flat object * json_unnest(json) => setof json
errorsif the json is not an array * json_unnest_each => setof (int, text, text)   errors if the array is not an array
offlat objects * populate_record(record, json) => record   errors if the json isn't a flat object *
populate_recordset(record,json) => setof record   errors if the json is not an array of flat objects
 

Note that I've added a couple of things to deal with json that 
represents a recordset (i.e. an array of objects). This is a very common 
pattern and one well worth optimizing for.

I think that would let you do a lot of what you want pretty cleanly.

cheers

andrew



pgsql-hackers by date:

Previous
From: Andres Freund
Date:
Subject: Re: Re: missing LockBuffer(buffer, BUFFER_LOCK_SHARE) in trigger.c GetTupleForTrigger?
Next
From: Merlin Moncure
Date:
Subject: Re: json accessors