42.5. 可信的和不可信的 PL/Perl

通常,PL/Perl 是作为一种叫plperl的"可信"编程语言安装的。在这种设置中, 为了保持安全,某些 Perl 操作被关闭掉了。通常,受限制的操作都是那些和环境相互交互的动作。 这包括文件句柄操作、requireuse(对于外部模块)。 没有办法访问数据库服务器进程内部或者获取具有服务器进程权限的 OS 级别的访问,就像 C 函数那样。 因此,任何非特权的数据库用户都可以允许使用这种语言。

这里是一个无法运转的函数的例子,因为出于安全原因,文件系统的操作是不允许的:

CREATE FUNCTION badfunc() RETURNS integer AS $$
    my $tmpfile = "/tmp/badfile";
    open my $fh, '>', $tmpfile
        or elog(ERROR, qq{could not open the file "$tmpfile": $!});
    print $fh "Testing writing to a file\n";
    close $fh or elog(ERROR, qq{could not close the file "$tmpfile": $!});
    return 1;
$$ LANGUAGE plperl;

创建这个函数将会失败,因为它使用的非法调用将会被验证器捕获。

有时候想写不受限制的 Perl 函数。比如,可能需要一个能发送邮件的 Perl 函数。为了处理这种情况, PL/Perl 也可以安装为"不可信的"的语言PL/PerlU。 在这种情况下,可以使用完整的 Perl 语言。当安装这个语言时,plperlu 这个名字可以选取不可信的 PL/Perl 变种。

PL/PerlU函数的作者必须注意不能把该函数用于做任何不想做的事情, 因为它可以干任何数据库管理员能干的事情。请注意数据库系统只允许数据库超级用户创建不可信语言写的函数。

如果上面的函数由超级用户用plperlu创建,那么执行就会成功。

同样的方式,如果语言被声明为plperlu而不是plperl, 那么用Perl写的匿名代码块可以使用受限制的操作,但是调用者必须是超级用户。

Note: 当PL/Perl函数在一个单独的为每个SQL用户的Perl解释器里运行时, 所有的PL/PerlU函数在一个单独的Perl解释器里的给定会话中执行 (不是用于PL/Perl函数的那个解释器)。这允许PL/PerlU 函数自由的分享数据,但是在PL/Perl和PL/PerlU 函数之间不会有通讯发生。

Note: Perl在一个进程中不能支持多个解释器,除非在编译时给它适当的标志,usemultiplicityuseithreads。(usemultiplicity是首选的,除非你实际需要使用线程。 获取更多信息,请参阅perlembed手册页。) 如果PL/Perl与一个没有这样编译的Perl的副本一起使用,那么每个会话只可能有一个Perl解释器, 所以任意一个会话只能执行PL/PerlU函数,或PL/Perl函数, 他们都是通过同一个SQL角色调用的。