我在带有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中,它被称为only time one should use utf8
。如果有的话,在脚本的输入包含非ASCII值的情况下,我可能希望
eval
版本在没有use utf8
的情况下中断。 (进一步的测试表明,将非ASCII值传递给bar()确实会导致eval失败,并出现相同的错误。)请注意,许多Postgres安装会在启动perl解释器时自动加载“utf8”。至少这是Debian中的默认设置,如执行
DO 'elog(WARNING, join ", ", sort keys %INC)' language plperl;
所示:但是在演示奇怪行为的机器上却不是这样:
这个问题不是关于如何让我的目标机器自动加载utf8的问题。我知道该怎么做。我很好奇为什么一开始它似乎是必要的。
最佳答案
在失败的版本中,您正在执行
$re = ''.qr/\b($re)\b/i
在后续版本中,您正在执行
$re = ''.qr/\b(foo)\b/i
当将模式编译为Unicode模式时(无论这是什么意思),听起来像qr//需要utf8.pm,但是后者没有被编译为Unicode模式。
加载utf8.pm失败是由于plperl创建的安全隔间强加了限制。
解决方法是将模块装入保险柜的外部。
解决方法是使用效率更高的
$re = '(?^u:\\b(?i:'.$re.')\\b)';
关于perl - 为什么此postgres存储过程想要 `use utf8`?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/20355007/