44.8. PL/Perl 深入了解

44.8.1. Configuration

本节列出了影响 PL/Perl 的配置参数。

  • plperl.on_init ( string )
    • 指定在 Perl 解释器专门供plperlplperlu使用之前,首次初始化 Perl 解释器时要执行的 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;

如果shared_preload_libraries中包含plperl库,则将在 Postmaster 中进行初始化,在这种情况下,应特别考虑破坏 Postmaster 稳定性的风险。使用此功能的主要原因是,仅在 postmaster 启动时才加载plperl.on_init加载的 Perl 模块,并且这些模块将立即可用,而无需在单个数据库会话中加载开销。但是,请记住,仅对于数据库会话使用的第一个 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 解释器分别专用于plperlplperlu时要执行的 Perl 代码。当在数据库会话中首次执行 PL/Perl 或 PL/PerlU 函数时,或者由于另外一种语言被调用或新的 SQL 角色调用 PL/Perl 函数而必须创建其他解释器时,就会发生这种情况。这是由plperl.on_init完成的任何初始化之后的。执行此代码时,SPI 功能不可用。 plperl.on_plperl_init中的 Perl 代码是在“锁定”解释器之后执行的,因此它只能执行受信任的操作。

如果代码由于错误而失败,它将中止初始化并传播到调用查询,从而导致当前事务或子事务中止。 Perl 中已经完成的任何操作都不会撤消;但是,该解释器将不再使用。如果再次使用该语言,将在新的 Perl 解释器中再次尝试初始化。

只有超级用户可以更改这些设置。尽管可以在会话中更改这些设置,但是这些更改不会影响已经用于执行功能的 Perl 解释器。

  • plperl.use_strict ( boolean )
    • 设置为 true 时,PL/Perl 函数的后续编译将启用strict pragma。此参数不会影响当前会话中已编译的函数。

44 .8.2. 局限性和缺少的功能

PL/Perl 当前缺少以下功能,但是它们会做出可喜的贡献。

  • PL/Perl 函数不能直接相互调用。

  • SPI 尚未完全实现。

  • 如果要使用spi_exec_query提取非常大的数据集,则应注意这些数据都将进入内存。如前所述,您可以使用spi_query/spi_fetchrow来避免这种情况。

如果集合返回函数通过return将大量行传递回 PostgreSQL,则会发生类似的问题。如前所述,您也可以通过对返回的每一行使用return_next来避免此问题。

  • 当会话正常结束(不是由于致命错误)时,将执行任何已定义的END块。当前没有执行其他操作。特别是,文件句柄不会自动刷新,对象也不会自动销毁。