Thread: Plperl and my() lexical variables bug?
Hi, I have something strange here, with Postgresql 8.1.4 under Linux ES 4, installed from the PG Group binaries: If I run this script: ---------------- CREATE OR REPLACE FUNCTION foo() RETURNS void AS $$ my $val; sub init { $val = @_[0]; elog(NOTICE, "1: @_[0]\n"); } &init(12); elog(NOTICE, "2: $val\n"); $$ LANGUAGE 'plperl'; select * from foo(); ---------------- I get in return something correct: ---------------- NOTICE: 1: 12 NOTICE: 2: 12 Total query runtime: 63 ms. Data retrieval runtime: 62 ms. 1 rows retrieved. ---------------- But then, if I simply call the function, with: ---------------- select * from foo(); ---------------- I get: ---------------- NOTICE: 1: 12 NOTICE: 2: Total query runtime: 63 ms. Data retrieval runtime: 62 ms. 1 rows retrieved. ---------------- $val variable is missing. Even more strange: if I replace "my $val;" with "$val;", this does not happen at all: ---------------- CREATE OR REPLACE FUNCTION foo() RETURNS void AS $$ $val; sub init { $val = @_[0]; elog(NOTICE, "1: @_[0]\n"); } &init(12); elog(NOTICE, "2: $val\n"); $$ LANGUAGE 'plperl'; ---------------- Now I can call the function with ---------------- select * from foo(); ---------------- it works as expected: ---------------- NOTICE: 1: 12 NOTICE: 2: 12 Total query runtime: 390 ms. Data retrieval runtime: 797 ms. 1 rows retrieved. ---------------- Am I missing something maybe? It sounds like a bug with lexical variables to me... Cheers, ---------------------------------- Philippe Lang, Ing. Dipl. EPFL Attik System rte de la Fonderie 2 1700 Fribourg Switzerland http://www.attiksystem.ch Tel: +41 (26) 422 13 75 Fax: +41 (26) 422 13 76
Attachment
On Fri, Jun 23, 2006 at 11:33:42AM +0200, Philippe Lang wrote: > Am I missing something maybe? It sounds like a bug with lexical variables to me... I think what's happening is that sub init is created once with $val referencing the lexically-scoped $val from sub foo's first invocation. When you call foo again, foo creates a new lexically-scoped $val but init's $val still refers to the object from foo's first call. You can see this if you display \$val: CREATE OR REPLACE FUNCTION foo() RETURNS void AS $$ my $val; sub init { $val = $_[0]; elog(NOTICE, "1: $_[0] " . \$val); } init(12); elog(NOTICE, "2: $val " . \$val); $$ LANGUAGE plperl; SELECT foo(); NOTICE: 1: 12 SCALAR(0x8447220) NOTICE: 2: 12 SCALAR(0x8447220) foo ----- (1 row) SELECT foo(); NOTICE: 1: 12 SCALAR(0x8447220) NOTICE: 2: SCALAR(0x83f5c4c) foo ----- (1 row) This behavior isn't specific to PL/Perl. A standalone Perl program exhibits the same behavior, so you might find a better explanation in a Perl-specific forum like the comp.lang.perl.misc newsgroup. -- Michael Fuhr
On Fri, Jun 23, 2006 at 07:49:19AM -0600, Michael Fuhr wrote: > This behavior isn't specific to PL/Perl. A standalone Perl program > exhibits the same behavior, so you might find a better explanation > in a Perl-specific forum like the comp.lang.perl.misc newsgroup. If you run it standalone with warnings enabled, you get this: Variable "$val" will not stay shared at a.pl line 6. Which is pretty much what is happening. There's plenty written about this on the web. This has a good summary as well as solutions: http://perl.com/pub/a/2002/05/07/mod_perl.html In particular, if you "use diagnostics" it suggests an anonymous sub will deal with it. Hope this helps, ---- a.pl ---- use warnings; use diagnostics; sub test { my $val; sub init { $val = $_[0]; print( "1: $_[0] " . \$val . "\n"); } init(12); print("2: $val " . \$val . "\n"); } test; test; --- snip --- -- Martijn van Oosterhout <kleptog@svana.org> http://svana.org/kleptog/ > From each according to his ability. To each according to his ability to litigate.