Fli*_*mzy 5 postgresql perl encoding utf-8 plperl
我在使用 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;
Run Code Online (Sandbox Code Playgroud)
执行时:
# select foo('foo');
ERROR: Unable to load utf8.pm into plperl at line 3.
BEGIN failed--compilation aborted.
CONTEXT: PL/Perl function "foo"
Run Code Online (Sandbox Code Playgroud)
但是,如果我将qr//操作移到 eval 中,它会起作用:
CREATE OR REPLACE FUNCTION bar(VARCHAR) RETURNS VARCHAR AS $$
my ( $re ) = @_;
eval "\$re = ''.qr/\\b($re)\\b/i;";
return $re;
$$ LANGUAGE plperl;
Run Code Online (Sandbox Code Playgroud)
结果:
# select bar('foo');
bar
-----------------
(?^i:\b(foo)\b)
(1 row)
Run Code Online (Sandbox Code Playgroud)
为什么 eval 绕过了自动的use utf8?
为什么首先use utf8需要?我的代码不是 UTF8,据说这是唯一一次应该use utf8.
如果有的话,在脚本的输入包含非 ASCII 值的情况下,我可能希望eval版本在没有use utf8的情况下中断。(进一步测试表明,将非 ASCII 值传递给 bar() 确实会导致 eval 失败并出现相同的错误)
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;我知道该怎么做。我很好奇为什么它首先似乎是必要的。
在失败的版本中,您正在执行
$re = ''.qr/\b($re)\b/i
Run Code Online (Sandbox Code Playgroud)
在成功的版本中,您正在执行
$re = ''.qr/\b(foo)\b/i
Run Code Online (Sandbox Code Playgroud)
听起来,当模式被编译为 Unicode 模式(无论这意味着什么)时,qr// 需要 utf8.pm,但后者不会被编译为 Unicode 模式。
无法加载 utf8.pm 是由于 plperl 创建的安全舱所施加的限制。
解决方法是将模块加载到安全隔间之外。
解决方法是使用更高效的
$re = '(?^u:\\b(?i:'.$re.')\\b)';
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
534 次 |
| 最近记录: |