我在使用 Perl 5.12.4 的 Postgres 9.2 上的 plperl 存储过程中遇到了一个特殊性。
可以使用这个“破碎”的 SP 来重现奇怪的行为:
CREATE FUNCTION foo(VARCHAR) RETURNS VARCHAR AS $$
my ( $re ) = @_;
$re = ''.qr/\b($re)\b/i;
return $re;
$$ LANGUAGE plperl;
执行时:
# select foo('foo');
ERROR: Unable to load utf8.pm into plperl at line 3.
BEGIN failed--compilation aborted.
CONTEXT: PL/Perl function "foo"
但是,如果我将qr//
操作移到 eval 中,它会起作用:
CREATE OR REPLACE FUNCTION bar(VARCHAR) RETURNS VARCHAR AS $$
my ( $re ) = @_;
eval "\$re = ''.qr/\\b($re)\\b/i;";
return $re;
$$ LANGUAGE plperl;
结果:
# select bar('foo');
bar
-----------------
(?^i:\b(foo)\b)
(1 row)
为什么评估绕过自动
use utf8
?为什么
use utf8
甚至首先需要?我的代码不是 UTF8,据说这是唯一一次应该use utf8
.如果有的话,如果脚本的输入包含非 ASCII 值,我可能希望
eval
版本在没有 的情况下中断。use utf8
(进一步的测试表明,将非 ASCII 值传递给 bar() 确实会导致 eval 失败并出现相同的错误)
请注意,许多 Postgres 安装会在 perl 解释器启动时自动加载“utf8”。这至少在 Debian 中是默认设置,如下所示
DO 'elog(WARNING, join ", ", sort keys %INC)' language plperl;
:
警告:Carp.pm、Carp/Heavy.pm、Exporter.pm、feature.pm、overload.pm、strict.pm、unicore/Heavy.pl、unicore/To/Fold.pl、unicore/lib/Perl/SpacePer。 pl、utf8.pm、utf8_heavy.pl、vars.pm、warnings.pm、warnings/register.pm
上下文:PL/Perl 匿名代码块
DO
但在展示奇怪行为的机器上却不是这样:
警告:Carp.pm、Carp/Heavy.pm、Exporter.pm、feature.pm、overload.pm、overloading.pm、strict.pm、vars.pm、warnings.pm、warnings/register.pm
上下文:PL/Perl匿名代码块
DO
这个问题不是关于如何让我的目标机器自动加载 utf8;我知道该怎么做。我很好奇为什么它似乎首先是必要的。