diff --git a/doc/src/sgml/plperl.sgml b/doc/src/sgml/plperl.sgml index 0680c6106e..c6fdb3bae2 100644 --- a/doc/src/sgml/plperl.sgml +++ b/doc/src/sgml/plperl.sgml @@ -1,5 +1,5 @@ @@ -182,8 +182,11 @@ $$ LANGUAGE plperl; SELECT * FROM perl_set(); - Note that when you do this, Perl will have to build the entire array in - memory; therefore the technique does not scale to very large result sets. + When you do this, Perl will have to build the entire array in memory; + therefore the technique does not scale to very large result sets. You + can instead call return_next for each element of + the result set, passing it either a scalar or a reference to a hash, + as appropriate to your function's return type. diff --git a/src/pl/plperl/SPI.xs b/src/pl/plperl/SPI.xs index cfcbc779a6..d1bab6d39b 100644 --- a/src/pl/plperl/SPI.xs +++ b/src/pl/plperl/SPI.xs @@ -98,7 +98,7 @@ spi_spi_exec_query(query, ...) RETVAL void -spi_spi_return_next(rv) +spi_return_next(rv) SV *rv; CODE: plperl_return_next(rv); diff --git a/src/pl/plperl/expected/plperl.out b/src/pl/plperl/expected/plperl.out index c488c4a4fc..ea067c9724 100644 --- a/src/pl/plperl/expected/plperl.out +++ b/src/pl/plperl/expected/plperl.out @@ -40,10 +40,7 @@ CREATE OR REPLACE FUNCTION perl_set_int(int) RETURNS SETOF INTEGER AS $$ return undef; $$ LANGUAGE plperl; SELECT perl_set_int(5); - perl_set_int --------------- -(0 rows) - +ERROR: set-valued function called in context that cannot accept a set SELECT * FROM perl_set_int(5); perl_set_int -------------- @@ -53,16 +50,7 @@ CREATE OR REPLACE FUNCTION perl_set_int(int) RETURNS SETOF INTEGER AS $$ return [0..$_[0]]; $$ LANGUAGE plperl; SELECT perl_set_int(5); - perl_set_int --------------- - 0 - 1 - 2 - 3 - 4 - 5 -(6 rows) - +ERROR: set-valued function called in context that cannot accept a set SELECT * FROM perl_set_int(5); perl_set_int -------------- @@ -109,10 +97,7 @@ CREATE OR REPLACE FUNCTION perl_set() RETURNS SETOF testrowperl AS $$ return undef; $$ LANGUAGE plperl; SELECT perl_set(); - perl_set ----------- -(0 rows) - +ERROR: set-valued function called in context that cannot accept a set SELECT * FROM perl_set(); f1 | f2 | f3 ----+----+---- @@ -126,9 +111,9 @@ CREATE OR REPLACE FUNCTION perl_set() RETURNS SETOF testrowperl AS $$ ]; $$ LANGUAGE plperl; SELECT perl_set(); -ERROR: elements of Perl result array must be reference to hash +ERROR: set-valued function called in context that cannot accept a set SELECT * FROM perl_set(); -ERROR: elements of Perl result array must be reference to hash +ERROR: setof-composite-returning Perl function must call return_next with reference to hash CREATE OR REPLACE FUNCTION perl_set() RETURNS SETOF testrowperl AS $$ return [ { f1 => 1, f2 => 'Hello', f3 => 'World' }, @@ -137,13 +122,7 @@ CREATE OR REPLACE FUNCTION perl_set() RETURNS SETOF testrowperl AS $$ ]; $$ LANGUAGE plperl; SELECT perl_set(); - perl_set ----------------------- - (1,Hello,World) - (2,Hello,PostgreSQL) - (3,Hello,PL/Perl) -(3 rows) - +ERROR: set-valued function called in context that cannot accept a set SELECT * FROM perl_set(); f1 | f2 | f3 ----+-------+------------ @@ -186,10 +165,7 @@ CREATE OR REPLACE FUNCTION perl_record_set() RETURNS SETOF record AS $$ return undef; $$ LANGUAGE plperl; SELECT perl_record_set(); - perl_record_set ------------------ -(0 rows) - +ERROR: set-valued function called in context that cannot accept a set SELECT * FROM perl_record_set(); ERROR: a column definition list is required for functions returning "record" SELECT * FROM perl_record_set() AS (f1 integer, f2 text, f3 text); @@ -205,11 +181,11 @@ CREATE OR REPLACE FUNCTION perl_record_set() RETURNS SETOF record AS $$ ]; $$ LANGUAGE plperl; SELECT perl_record_set(); -ERROR: function returning record called in context that cannot accept type record +ERROR: set-valued function called in context that cannot accept a set SELECT * FROM perl_record_set(); ERROR: a column definition list is required for functions returning "record" SELECT * FROM perl_record_set() AS (f1 integer, f2 text, f3 text); -ERROR: elements of Perl result array must be reference to hash +ERROR: setof-composite-returning Perl function must call return_next with reference to hash CREATE OR REPLACE FUNCTION perl_record_set() RETURNS SETOF record AS $$ return [ { f1 => 1, f2 => 'Hello', f3 => 'World' }, @@ -218,7 +194,7 @@ CREATE OR REPLACE FUNCTION perl_record_set() RETURNS SETOF record AS $$ ]; $$ LANGUAGE plperl; SELECT perl_record_set(); -ERROR: function returning record called in context that cannot accept type record +ERROR: set-valued function called in context that cannot accept a set SELECT * FROM perl_record_set(); ERROR: a column definition list is required for functions returning "record" SELECT * FROM perl_record_set() AS (f1 integer, f2 text, f3 text); @@ -261,13 +237,7 @@ RETURNS SETOF record AS $$ ]; $$ LANGUAGE plperl; SELECT perl_out_params_set(); - perl_out_params_set ----------------------- - (1,Hello,World) - (2,Hello,PostgreSQL) - (3,Hello,PL/Perl) -(3 rows) - +ERROR: set-valued function called in context that cannot accept a set SELECT * FROM perl_out_params_set(); f1 | f2 | f3 ----+-------+------------ @@ -277,13 +247,7 @@ SELECT * FROM perl_out_params_set(); (3 rows) SELECT (perl_out_params_set()).f3; - f3 ------------- - World - PostgreSQL - PL/Perl -(3 rows) - +ERROR: set-valued function called in context that cannot accept a set -- -- Check behavior with erroneous return values -- @@ -323,12 +287,12 @@ CREATE OR REPLACE FUNCTION foo_set_bad() RETURNS SETOF footype AS $$ return 42; $$ LANGUAGE plperl; SELECT * FROM foo_set_bad(); -ERROR: set-returning Perl function must return reference to array +ERROR: set-returning Perl function must return reference to array or use return_next CREATE OR REPLACE FUNCTION foo_set_bad() RETURNS SETOF footype AS $$ return {y => 3, z => 4}; $$ LANGUAGE plperl; SELECT * FROM foo_set_bad(); -ERROR: set-returning Perl function must return reference to array +ERROR: set-returning Perl function must return reference to array or use return_next CREATE OR REPLACE FUNCTION foo_set_bad() RETURNS SETOF footype AS $$ return [ [1, 2], @@ -336,7 +300,7 @@ return [ ]; $$ LANGUAGE plperl; SELECT * FROM foo_set_bad(); -ERROR: elements of Perl result array must be reference to hash +ERROR: setof-composite-returning Perl function must call return_next with reference to hash CREATE OR REPLACE FUNCTION foo_set_bad() RETURNS SETOF footype AS $$ return [ {y => 3, z => 4} @@ -368,3 +332,21 @@ SELECT perl_get_field((11,12), 'z'); (1 row) +-- +-- Test return_next +-- +CREATE OR REPLACE FUNCTION perl_srf_rn() RETURNS SETOF RECORD AS $$ +$i = 0; +for ("World", "PostgreSQL", "PL/Perl") { + return_next({f1=>++$i, f2=>'Hello', f3=>$_}); +} +return; +$$ language plperl; +SELECT * from perl_srf_rn() AS (f1 INTEGER, f2 TEXT, f3 TEXT); + f1 | f2 | f3 +----+-------+------------ + 1 | Hello | World + 2 | Hello | PostgreSQL + 3 | Hello | PL/Perl +(3 rows) + diff --git a/src/pl/plperl/plperl.c b/src/pl/plperl/plperl.c index 82fdb86b18..6cd3494fb9 100644 --- a/src/pl/plperl/plperl.c +++ b/src/pl/plperl/plperl.c @@ -33,7 +33,7 @@ * ENHANCEMENTS, OR MODIFICATIONS. * * IDENTIFICATION - * $PostgreSQL: pgsql/src/pl/plperl/plperl.c,v 1.75 2005/06/04 20:33:06 momjian Exp $ + * $PostgreSQL: pgsql/src/pl/plperl/plperl.c,v 1.76 2005/06/05 03:16:35 momjian Exp $ * **********************************************************************/ @@ -222,7 +222,7 @@ plperl_safe_init(void) "use vars qw($PLContainer); $PLContainer = new Safe('PLPerl');" "$PLContainer->permit_only(':default');" "$PLContainer->permit(qw[:base_math !:base_io sort time]);" - "$PLContainer->share(qw[&elog &spi_exec_query &spi_return_next " + "$PLContainer->share(qw[&elog &spi_exec_query &return_next " "&DEBUG &LOG &INFO &NOTICE &WARNING &ERROR %_SHARED ]);" ; diff --git a/src/pl/plperl/sql/plperl.sql b/src/pl/plperl/sql/plperl.sql index 0cfcd1752d..3e601173dd 100644 --- a/src/pl/plperl/sql/plperl.sql +++ b/src/pl/plperl/sql/plperl.sql @@ -234,3 +234,16 @@ $$ LANGUAGE plperl; SELECT perl_get_field((11,12), 'x'); SELECT perl_get_field((11,12), 'y'); SELECT perl_get_field((11,12), 'z'); + +-- +-- Test return_next +-- + +CREATE OR REPLACE FUNCTION perl_srf_rn() RETURNS SETOF RECORD AS $$ +$i = 0; +for ("World", "PostgreSQL", "PL/Perl") { + return_next({f1=>++$i, f2=>'Hello', f3=>$_}); +} +return; +$$ language plperl; +SELECT * from perl_srf_rn() AS (f1 INTEGER, f2 TEXT, f3 TEXT);