I wrote:
> I'm inclined to think that auto-dereference is indeed a good idea,
> and am tempted to go make that change to make all this consistent.
> Comments?

Here's a draft patch for that.  I ended up only changing
plperl_sv_to_datum.  There is maybe a case for doing something
similar in plperl_return_next_internal's fn_retistuple code path,
so that you can return a reference-to-reference-to-hash there;
but I was unable to muster much enthusiasm for touching that.

                        regards, tom lane

diff --git a/src/pl/plperl/expected/plperl.out b/src/pl/plperl/expected/plperl.out
index ebfba3e..d8a1ff5 100644
*** a/src/pl/plperl/expected/plperl.out
--- b/src/pl/plperl/expected/plperl.out
*************** $$ LANGUAGE plperl;
*** 763,776 ****
  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"
  -- 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;');
--- 763,779 ----
  SELECT text_obj();
  ERROR:  cannot convert Perl hash to non-composite type text
  CONTEXT:  PL/Perl function "text_obj"
! -- 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();
!  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;');
diff --git a/src/pl/plperl/plperl.c b/src/pl/plperl/plperl.c
index 4342c02..4cfc506 100644
*** a/src/pl/plperl/plperl.c
--- b/src/pl/plperl/plperl.c
*************** plperl_sv_to_datum(SV *sv, Oid typid, in
*** 1402,1412 ****
  			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 */
  	}
  	else
  	{
--- 1402,1414 ----
  			return ret;
  		}
  
! 		/*
! 		 * 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
  	{
diff --git a/src/pl/plperl/sql/plperl.sql b/src/pl/plperl/sql/plperl.sql
index c36da0f..b0d950b 100644
*** a/src/pl/plperl/sql/plperl.sql
--- b/src/pl/plperl/sql/plperl.sql
*************** $$ LANGUAGE plperl;
*** 504,510 ****
  
  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;
--- 504,510 ----
  
  SELECT text_obj();
  
! -- test looking through a scalar ref
  CREATE OR REPLACE FUNCTION text_scalarref() RETURNS text AS $$
  	my $str = 'str';
  	return \$str;

Reply via email to