Re: WIP json generation enhancements - Mailing list pgsql-hackers

From Merlin Moncure
Subject Re: WIP json generation enhancements
Date
Msg-id CAHyXU0w6g2o8mMy=jyeXrfSpZUWF38LMYyz3Xjk5PC7o_u_-_A@mail.gmail.com
Whole thread Raw
In response to Re: WIP json generation enhancements  (Dimitri Fontaine <dimitri@2ndQuadrant.fr>)
List pgsql-hackers
On Thu, Nov 22, 2012 at 4:54 AM, Dimitri Fontaine
<dimitri@2ndquadrant.fr> wrote:
> Andrew Dunstan <andrew@dunslane.net> writes:
>> Here is a WIP patch for enhancements to json generation.
>>
>> First, there is the much_requested json_agg, which will aggregate rows
>> directly to json. So the following will now work:
>>
>>     select json_agg(my_table) from mytable;
>>     select json_agg(q) from (<myquery here>) q;
>
> Awesome, thanks!
>
> How do you handle the nesting of the source elements? I would expect a
> variant of the aggregate that takes two input parameters, the datum and
> the current nesting level.
>
> Consider a tree table using parent_id and a recursive query to display
> the tree. You typically handle the nesting with an accumulator and a
> call to repeat() to prepend some spaces before the value columns. What
> about passing that nesting level (integer) to the json_agg()?
>
> Here's a worked out example:
>
>     CREATE TABLE parent_child (
>         parent_id integer NOT NULL,
>         this_node_id integer NULL
>     );
>
>     INSERT INTO parent_child (parent_id, this_node_id) VALUES (0, 1);
>     INSERT INTO parent_child (parent_id, this_node_id) VALUES (1, 2);
>     INSERT INTO parent_child (parent_id, this_node_id) VALUES (1, 3);
>     INSERT INTO parent_child (parent_id, this_node_id) VALUES (1, 4);
>     INSERT INTO parent_child (parent_id, this_node_id) VALUES (2, 5);
>     INSERT INTO parent_child (parent_id, this_node_id) VALUES (2, 6);
>     INSERT INTO parent_child (parent_id, this_node_id) VALUES (4, 7);
>     INSERT INTO parent_child (parent_id, this_node_id) VALUES (4, 8);
>     INSERT INTO parent_child (parent_id, this_node_id) VALUES (4, 9);
>     INSERT INTO parent_child (parent_id, this_node_id) VALUES (9, 10);
>
>
>     WITH RECURSIVE tree(id, level, parents) AS (
>         SELECT this_node_id as id, 0 as level, '{}'::int[] as parents
>           FROM parent_child
>          WHERE parent_id = 0
>
>         UNION ALL
>
>         SELECT this_node_id as id, t.level + 1, t.parents || c.parent_id
>           FROM parent_child c
>           JOIN tree t ON t.id = c.parent_id
>     )
>     SELECT json_agg(id, level)
>       FROM tree;
>
> I've left the parents column in the query above as a debug facility, but
> it's not needed in that case.

I don't think there is any way a json_agg() function could reasonably
do this.  The only possible dataset it could work on would be for
homogeneously typed array-like data which is not very interesting for
the broader case of nested json productions. I think the right way to
do it is to work out the precise structure in sql and do the
transformation directly on the type using the already existing
transformation functions.

That said, recursive structures are a pain presently because postgres
composite types are not allowed to be recursive.  So ISTM getting that
restriction relaxed is the way to go; then you build it in sql and
just fire whatever xxx_to_json happens to be the most
appropriate...then your example would be a snap.

merlin



pgsql-hackers by date:

Previous
From: Robert Haas
Date:
Subject: Re: WIP json generation enhancements
Next
From: Robert Haas
Date:
Subject: Re: Suggestion for --truncate-tables to pg_restore