42.7. PL/Perl 内部机制 #
42.7.1. 配置 #
本节列出影响 PL/Perl 的配置参数。
-
plperl.on_init(string) # 指定在 Perl 解释器首次初始化时、在它被专用于
plperl或plperlu之前,要执行的 Perl 代码。执行这段代码时 SPI 函数不可用。如果代码因错误而失败,就会中止解释器初始化,并把错误传播到调用查询,导致当前事务或子事务被中止。Perl 代码仅限一个字符串。更长的代码可以放在模块中,并由
on_init字符串加载。示例:plperl.on_init = 'require "plperlinit.pl"' plperl.on_init = 'use lib "/my/app"; use MyApp::PgInit;'
任何通过
plperl.on_init直接或间接加载的模块,都可供plperl使用。这可能带来安全风险。要查看已经加载了哪些模块,可以使用:DO 'elog(WARNING, join ", ", sort keys %INC)' LANGUAGE plperl;
如果 plperl 库被包含在shared_preload_libraries中,初始化就会在 postmaster 中发生;在这种情况下,需要额外考虑使 postmaster 不稳定的风险。使用此特性的主要原因是,通过
plperl.on_init加载的 Perl 模块只需在 postmaster 启动时加载一次,之后在各个数据库会话中都可立即使用,而无需承担加载开销。不过要记住,这种开销只会对数据库会话使用的第一个 Perl 解释器被省掉,也就是 PL/PerlU,或者第一个调用 PL/Perl 函数的 SQL 角色所对应的 PL/Perl。数据库会话中后来创建的任何额外 Perl 解释器,都必须重新执行plperl.on_init。此外,在 Windows 上预加载完全不会带来节省,因为在 postmaster 进程中创建的 Perl 解释器不会传播到子进程中。这个参数只能在
postgresql.conf文件中,或在服务器命令行上设置。-
plperl.on_plperl_init(string)
plperl.on_plperlu_init(string) # 这些参数分别指定在 Perl 解释器被专用于
plperl或plperlu时要执行的 Perl 代码。这会在数据库会话中首次执行 PL/Perl 或 PL/PerlU 函数时发生;如果因为调用另一种语言,或某个新的 SQL 角色调用了 PL/Perl 函数而需要创建额外解释器时,也会发生。这是在plperl.on_init完成的任何初始化之后进行的。执行这段代码时 SPI 函数不可用。plperl.on_plperl_init中的 Perl 代码是在对解释器进行“锁定”之后执行的,因此只能执行受信任的操作。如果代码因错误而失败,就会中止初始化,并把错误传播到调用查询,导致当前事务或子事务被中止。在 Perl 中已经完成的任何动作都不会被撤销;不过,该解释器将不再被使用。如果再次使用该语言,就会在一个新的 Perl 解释器中再次尝试初始化。
只有超级用户可以更改这些设置。尽管这些设置可以在会话中修改,但这类更改不会影响已经用于执行函数的 Perl 解释器。
-
plperl.use_strict(boolean) # 如果将其设为真,后续编译的 PL/Perl 函数都会启用
strict编译指示。该参数不影响当前会话中已经编译的函数。
42.7.2. 限制与缺失特性 #
PL/Perl 目前仍缺少下列特性,但欢迎为此作出贡献。
PL/Perl 函数不能直接调用彼此。
SPI 尚未完全实现。
如果使用
spi_exec_query取回非常大的数据集,应注意这些数据都会进入内存。可以像前面所示那样,通过使用spi_query/spi_fetchrow来避免这种情况。如果集合返回函数通过
return把一个大型行集返回给 PostgreSQL,也会出现类似问题。前面已经说明过,可以改为对每一行使用return_next,从而避免这个问题。当会话正常结束(而不是由于致命错误结束)时,任何已经定义的
END块都会被执行。目前不会执行其他操作。具体来说,文件句柄不会自动刷写,对象也不会自动销毁。