Обсуждение: 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
Вложения
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.