Allow plperl_sv_to_datum to look through scalar refs.
authorTom Lane <tgl@sss.pgh.pa.us>
Mon, 18 Jun 2018 19:31:57 +0000 (15:31 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Mon, 18 Jun 2018 19:31:57 +0000 (15:31 -0400)
There seems little reason for the policy of throwing error if we
find a ref to something other than a hash or array.   Recursively
look through the ref, instead.  This makes the behavior in non-transform
cases comparable to what was already instantiated for jsonb_plperl.

Note that because we invoke any available transform function before
considering the ref case, it's up to each transform function whether
it wants to play along with this behavior or do something different.

Because the previous behavior was just to throw a useless error,
this seems unlikely to create any compatibility issues.  Still, given
the lack of field complaints so far, seems best not to back-patch.

Discussion: https://postgr.es/m/28336.1528393969@sss.pgh.pa.us

src/pl/plperl/expected/plperl.out
src/pl/plperl/plperl.c
src/pl/plperl/sql/plperl.sql

index ebfba3eb8d0e30e8f6bca0e15da777a58b31d3c6..d8a1ff5dd8d1c9b1d0451510ea803ee3dc9980a2 100644 (file)
@@ -763,14 +763,17 @@ $$ LANGUAGE plperl;
 SELECT text_obj();
 ERROR:  cannot convert Perl hash to non-composite type text
 CONTEXT:  PL/Perl function "text_obj"
------ make sure we can't return a scalar ref
+-- test looking through a scalar ref
 CREATE OR REPLACE FUNCTION text_scalarref() RETURNS text AS $$
        my $str = 'str';
        return \$str;
 $$ LANGUAGE plperl;
 SELECT text_scalarref();
-ERROR:  PL/Perl function must return reference to hash or array
-CONTEXT:  PL/Perl function "text_scalarref"
+ text_scalarref 
+----------------
+ str
+(1 row)
+
 -- check safe behavior when a function body is replaced during execution
 CREATE OR REPLACE FUNCTION self_modify(INTEGER) RETURNS INTEGER AS $$
    spi_exec_query('CREATE OR REPLACE FUNCTION self_modify(INTEGER) RETURNS INTEGER AS \'return $_[0] * 3;\' LANGUAGE plperl;');
index 4342c02b272e0dd7f8f8a58a14d387c14fa94dcb..4cfc5062531d0c5d97b0afbee648384bbbea445a 100644 (file)
@@ -1402,11 +1402,13 @@ plperl_sv_to_datum(SV *sv, Oid typid, int32 typmod,
                        return ret;
                }
 
-               /* Reference, but not reference to hash or array ... */
-               ereport(ERROR,
-                               (errcode(ERRCODE_DATATYPE_MISMATCH),
-                                errmsg("PL/Perl function must return reference to hash or array")));
-               return (Datum) 0;               /* shut up compiler */
+               /*
+                * If it's a reference to something else, such as a scalar, just
+                * recursively look through the reference.
+                */
+               return plperl_sv_to_datum(SvRV(sv), typid, typmod,
+                                                                 fcinfo, finfo, typioparam,
+                                                                 isnull);
        }
        else
        {
index c36da0ff043bc9eeac6f6be35eee7ffa9c7c9694..b0d950b2304a03f91d7604166c99506e3f68ce8f 100644 (file)
@@ -504,7 +504,7 @@ $$ LANGUAGE plperl;
 
 SELECT text_obj();
 
------ make sure we can't return a scalar ref
+-- test looking through a scalar ref
 CREATE OR REPLACE FUNCTION text_scalarref() RETURNS text AS $$
        my $str = 'str';
        return \$str;