On 28th of March 2018, Peter Eisentraut committed patch:

Transforms for jsonb to PL/Python
 
Add a new contrib module jsonb_plpython that provide a transform between
jsonb and PL/Python.  jsonb values are converted to appropriate Python
types such as dicts and lists, and vice versa.
 
Author: Anthony Bykov <a.bykov@postgrespro.ru>

and then, on 3rd of April 2018, he also committed patch:

Transforms for jsonb to PL/Perl
 
Add a new contrib module jsonb_plperl that provides a transform between
jsonb and PL/Perl.  jsonb values are converted to appropriate Perl types
such as arrays and hashes, and vice versa.
 
Author: Anthony Bykov <a.bykov@postgrespro.ru>

Well, I don't really write in Python, but I can show you what this is about in Perl.

Before, for example in PostgreSQL 10, when you passed jsonb to PL/Perl function:

CREATE OR REPLACE FUNCTION testit(jsonb) RETURNS void as $$
my $arg = shift;
elog(NOTICE, "Arg is: [$arg]");
elog(NOTICE, "Arg ref is: [" . ref($arg) . "]");
elog(NOTICE, "Arg len is: [" . length($arg) . "]");
$$ language plperl;
 
SELECT testit( '{ "id": 1, "name": "A green door", "price": 12.50, "tags": ["home", "green"] }'::jsonb );
psql:test.sql:11: NOTICE:  Arg is: [{"id": 1, "name": "A green door", "tags": ["home", "green"], "price": 12.50}]
psql:test.sql:11: NOTICE:  Arg ref is: []
psql:test.sql:11: NOTICE:  Arg len is: [76]
 testit
--------
 
(1 row)

The value was passed as simple string.

But now, in Pg11:

CREATE OR REPLACE FUNCTION testit(jsonb)
    RETURNS void
    TRANSFORM FOR TYPE jsonb
    LANGUAGE plperl
as $$
my $arg = shift;
elog(NOTICE, "Arg is: [$arg]");
elog(NOTICE, "Arg ref is: [" . ref($arg) . "]");
elog(NOTICE, "Arg len is: [" . length($arg) . "]");
$$;
 
SELECT testit( '{ "id": 1, "name": "A green door", "price": 12.50, "tags": ["home", "green"] }'::jsonb );
psql:test.sql:15: NOTICE:  Arg is: [HASH(0x558375ceb000)]
psql:test.sql:15: NOTICE:  Arg ref is: [HASH]
psql:test.sql:15: NOTICE:  Arg len is: [20]
 testit 
--------
 
(1 row)

Function definition needs “TRANSFORM" clause, but aside from this – it's brilliant. Having the value parsed into proper hash means we can easily scan it, modify and do whatever we need or want.

That's a great addition. Thanks a lot guys 🙂

  1. One comment

  2. # Jonathan S. Katz
    Apr 17, 2018

    Thanks for writing this up! Here is an example with Python 2:

    CREATE LANGUAGE plpython2u;
     
    /** Pre-11 */
    CREATE OR REPLACE FUNCTION testit(d jsonb)
        RETURNS void
        LANGUAGE plpython2u
    as $$
        print d
        print type(d)
        print len(d)
    $$;
     
    /** Post-11 */
    CREATE EXTENSION jsonb_plpython2u CASCADE;
    CREATE OR REPLACE FUNCTION testit(d jsonb)
        RETURNS void
        TRANSFORM FOR TYPE jsonb
        LANGUAGE plpython2u
    as $$
        print d
        print type(d)
        print len(d)
    $$;

Leave a comment