From: | "Kynn Jones" <kynnjo(at)gmail(dot)com> |
---|---|
To: | "pgsql-general General" <pgsql-general(at)postgresql(dot)org> |
Subject: | On defining Perl functions within PLPERL code |
Date: | 2008-03-10 21:11:40 |
Message-ID: | c2350ba40803101411x7d941116g8740f80ef3b0c567@mail.gmail.com |
Views: | Raw Message | Whole Thread | Download mbox | Resend email |
Thread: | |
Lists: | pgsql-general |
In a recent post I mentioned that I had a PLPERL procedure that
...adds useful definitions, mostly subs, to Perl's main package.
I thought this claim needs further clarification, since the docs for PLPERL
include a warning that may give readers the impression that defining Perl
functions within PLPERL code is somehow problematic. This warning says:
Note: The use of named nested subroutines is dangerous in Perl, especially
> if they refer to lexical variables in the enclosing scope. Because a PL/Perl
> function is wrapped in a subroutine, any named subroutine you create will be
> nested. In general, it is far safer to create anonymous subroutines which
> you call via a coderef.
>
But this is only a problem if one defines functions like this
sub foo {
# blah blah blah
}
which indeed would result in a nested function. But one can define
non-nested functions within other functions (and even "closures" that refer
to lexical variables) by manipulating symbol tables directly. For example:
CREATE FUNCTION make_closure ( TEXT ) RETURNS void
AS $PERL$
my $lexical = shift;
*the_closure = sub { return '>> ' . $lexical };
$PERL$ LANGUAGE plperl IMMUTABLE;
CREATE FUNCTION test_closure () RETURNS TEXT
AS $PERL$
return the_closure();
$PERL$ LANGUAGE plperl VOLATILE;
First, we show that the perl function the_closure (or more precisely,
main::the_closure) has not been defined yet.
SELECT * from test_closure();
ERROR: error from Perl function: Undefined subroutine &main::the_closure
called at line 2.
As expected. To define the perl function the_closure, we need to call
make_closure first:
SELECT make_closure( 'foobar' );
SELECT * from test_closure();
test_closure
--------------
>> foobar
(1 row)
Now the PLPERL procedure test_closure() can invoke the perl function
the_closure.
The next (very contrived) example demonstrates that the functions being
defined are indeed closures (note that each of the Perl functions defined
through calls to make_closure2 refers to its own private copy of the
variable $lexical). (Note that this example uses a "soft reference", but
one can achieve the same thing by eval'ing a suitable string).
CREATE FUNCTION make_closure2 ( TEXT, TEXT ) RETURNS void
AS $PERL$
my $closure_name = shift;
my $lexical = shift;
*{ $closure_name } = sub { return '>> ' . $lexical };
return;
$PERL$ LANGUAGE plperlu IMMUTABLE;
CREATE FUNCTION test_closure2 ( TEXT ) RETURNS TEXT
AS $PERL$
my $ret = eval( shift() . '()' );
die if $@;
return $ret;
$PERL$ LANGUAGE plperlu VOLATILE;
SELECT make_closure2( 'first_closure', 'quux' );
SELECT make_closure2( 'second_closure', 'frobozz' );
SELECT * FROM test_closure2( 'first_closure' );
test_closure2
---------------
>> quux
(1 row)
SELECT * FROM test_closure2( 'second_closure' );
test_closure2
---------------
>> frobozz
(1 row)
And the functions need not to be defined in the main package. For example,
make_closure3 is exactly like make_closure above, except that it defines the
function the_closure in the package Some::Other::Package rather than the
package main. (Similarly, test_closure3 is exactly like test_closure,
except that it invokes Some::Other::Package::the_closure rather than
main::the_closure.)
CREATE FUNCTION make_closure3 ( TEXT ) RETURNS void
AS $PERL$
my $lexical = shift;
*Some::Other::Package::the_closure = sub { return '>> ' . $lexical };
$PERL$ LANGUAGE plperl IMMUTABLE;
CREATE FUNCTION test_closure3 () RETURNS TEXT
AS $PERL$
return Some::Other::Package::the_closure();
$PERL$ LANGUAGE plperl VOLATILE;
SELECT make_closure3( 'mwa-ha-ha-ha-ha!' );
SELECT * from test_closure3();
test_closure3
---------------------
>> mwa-ha-ha-ha-ha!
(1 row)
I want to point out that such symbol-table manipulations are entirely
standard. For example, the standard Perl module Exporter uses this
technique to install functions and variables in the calling package's
namespace.
Kynn
From | Date | Subject | |
---|---|---|---|
Next Message | John Cartwright | 2008-03-10 21:13:29 | Re: php pg_connect fails, pgsql works |
Previous Message | Tom Lane | 2008-03-10 21:08:28 | Re: pg_type.relacl |