Commit 23610daf authored by Tom Lane's avatar Tom Lane

Fix up Perl-to-Postgres datatype conversions in pl/perl.

This patch restores the pre-9.1 behavior that pl/perl functions returning
VOID ignore the result value of their last Perl statement.  9.1.0
unintentionally threw an error if the last statement returned a reference,
as reported by Amit Khandekar.

Also, make sure it works to return a string value for a composite type,
so long as the string meets the type's input format.  We already allowed
the equivalent behavior for arrays, so it seems inconsistent to not allow
it for composites.

In addition, ensure we throw errors for attempts to return arrays or hashes
when the function's declared result type is not an array or composite type,
respectively.  Pre-9.1 versions rather uselessly returned strings like
ARRAY(0x221a9a0) or HASH(0x221aa90), while 9.1.0 threw an error for the
hash case and returned a garbage value for the array case.

Also, clean up assorted grotty coding in Perl array conversion, including
use of a session-lifespan memory context to accumulate the array value
(resulting in session-lifespan memory leak on error), failure to apply the
declared typmod if any, and failure to detect some cases of non-rectangular
multi-dimensional arrays.

Alex Hunsaker and Tom Lane
parent fb4340c5
......@@ -101,6 +101,16 @@ SELECT * FROM perl_row();
1 | hello | world | ({{1}})
(1 row)
-- test returning a composite literal
CREATE OR REPLACE FUNCTION perl_row_lit() RETURNS testrowperl AS $$
return '(1,hello,world,"({{1}})")';
$$ LANGUAGE plperl;
SELECT perl_row_lit();
perl_row_lit
---------------------------
(1,hello,world,"({{1}})")
(1 row)
CREATE OR REPLACE FUNCTION perl_set() RETURNS SETOF testrowperl AS $$
return undef;
$$ LANGUAGE plperl;
......@@ -336,7 +346,8 @@ CREATE OR REPLACE FUNCTION foo_bad() RETURNS footype AS $$
return 42;
$$ LANGUAGE plperl;
SELECT * FROM foo_bad();
ERROR: composite-returning PL/Perl function must return reference to hash
ERROR: malformed record literal: "42"
DETAIL: Missing left parenthesis.
CONTEXT: PL/Perl function "foo_bad"
CREATE OR REPLACE FUNCTION foo_bad() RETURNS footype AS $$
return [
......@@ -345,7 +356,7 @@ return [
];
$$ LANGUAGE plperl;
SELECT * FROM foo_bad();
ERROR: composite-returning PL/Perl function must return reference to hash
ERROR: cannot convert Perl array to non-array type footype
CONTEXT: PL/Perl function "foo_bad"
CREATE OR REPLACE FUNCTION foo_set_bad() RETURNS SETOF footype AS $$
return 42;
......@@ -639,3 +650,46 @@ CONTEXT: PL/Perl anonymous code block
DO $do$ use warnings FATAL => qw(void) ; my @y; my $x = sort @y; 1; $do$ LANGUAGE plperl;
ERROR: Useless use of sort in scalar context at line 1.
CONTEXT: PL/Perl anonymous code block
-- make sure functions marked as VOID without an explicit return work
CREATE OR REPLACE FUNCTION myfuncs() RETURNS void AS $$
$_SHARED{myquote} = sub {
my $arg = shift;
$arg =~ s/(['\\])/\\$1/g;
return "'$arg'";
};
$$ LANGUAGE plperl;
SELECT myfuncs();
myfuncs
---------
(1 row)
-- make sure we can't return an array as a scalar
CREATE OR REPLACE FUNCTION text_arrayref() RETURNS text AS $$
return ['array'];
$$ LANGUAGE plperl;
SELECT text_arrayref();
ERROR: cannot convert Perl array to non-array type text
CONTEXT: PL/Perl function "text_arrayref"
--- make sure we can't return a hash as a scalar
CREATE OR REPLACE FUNCTION text_hashref() RETURNS text AS $$
return {'hash'=>1};
$$ LANGUAGE plperl;
SELECT text_hashref();
ERROR: cannot convert Perl hash to non-composite type text
CONTEXT: PL/Perl function "text_hashref"
---- make sure we can't return a blessed object as a scalar
CREATE OR REPLACE FUNCTION text_obj() RETURNS text AS $$
return bless({}, 'Fake::Object');
$$ 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
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"
......@@ -204,6 +204,16 @@ select plperl_arrays_inout('{{1}, {2}, {3}}');
{{1},{2},{3}}
(1 row)
-- check that we can return an array literal
CREATE OR REPLACE FUNCTION plperl_arrays_inout_l(INTEGER[]) returns INTEGER[] AS $$
return shift.''; # stringify it
$$ LANGUAGE plperl;
select plperl_arrays_inout_l('{{1}, {2}, {3}}');
plperl_arrays_inout_l
-----------------------
{{1},{2},{3}}
(1 row)
-- make sure setof works
create or replace function perl_setof_array(integer[]) returns setof integer[] language plperl as $$
my $arr = shift;
......
This diff is collapsed.
......@@ -50,6 +50,13 @@ $$ LANGUAGE plperl;
SELECT perl_row();
SELECT * FROM perl_row();
-- test returning a composite literal
CREATE OR REPLACE FUNCTION perl_row_lit() RETURNS testrowperl AS $$
return '(1,hello,world,"({{1}})")';
$$ LANGUAGE plperl;
SELECT perl_row_lit();
CREATE OR REPLACE FUNCTION perl_set() RETURNS SETOF testrowperl AS $$
return undef;
......@@ -415,3 +422,43 @@ DO $do$ use strict; my $name = "foo"; my $ref = $$name; $do$ LANGUAGE plperl;
-- check that we can "use warnings" (in this case to turn a warn into an error)
-- yields "ERROR: Useless use of sort in scalar context."
DO $do$ use warnings FATAL => qw(void) ; my @y; my $x = sort @y; 1; $do$ LANGUAGE plperl;
-- make sure functions marked as VOID without an explicit return work
CREATE OR REPLACE FUNCTION myfuncs() RETURNS void AS $$
$_SHARED{myquote} = sub {
my $arg = shift;
$arg =~ s/(['\\])/\\$1/g;
return "'$arg'";
};
$$ LANGUAGE plperl;
SELECT myfuncs();
-- make sure we can't return an array as a scalar
CREATE OR REPLACE FUNCTION text_arrayref() RETURNS text AS $$
return ['array'];
$$ LANGUAGE plperl;
SELECT text_arrayref();
--- make sure we can't return a hash as a scalar
CREATE OR REPLACE FUNCTION text_hashref() RETURNS text AS $$
return {'hash'=>1};
$$ LANGUAGE plperl;
SELECT text_hashref();
---- make sure we can't return a blessed object as a scalar
CREATE OR REPLACE FUNCTION text_obj() RETURNS text AS $$
return bless({}, 'Fake::Object');
$$ LANGUAGE plperl;
SELECT text_obj();
----- make sure we can't return a scalar ref
CREATE OR REPLACE FUNCTION text_scalarref() RETURNS text AS $$
my $str = 'str';
return \$str;
$$ LANGUAGE plperl;
SELECT text_scalarref();
......@@ -152,6 +152,13 @@ $$ LANGUAGE plperl;
select plperl_arrays_inout('{{1}, {2}, {3}}');
-- check that we can return an array literal
CREATE OR REPLACE FUNCTION plperl_arrays_inout_l(INTEGER[]) returns INTEGER[] AS $$
return shift.''; # stringify it
$$ LANGUAGE plperl;
select plperl_arrays_inout_l('{{1}, {2}, {3}}');
-- make sure setof works
create or replace function perl_setof_array(integer[]) returns setof integer[] language plperl as $$
my $arr = shift;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment