为什么这个postgres存储过程想要'使用utf8`?

时间:2013-12-03 15:24:05

标签: perl postgresql 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;

执行时:

# 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)
  1. 为什么eval会绕过自动use utf8

  2. 为什么首先要求use utf8?我的代码不是UTF8,据说是only time one should use utf8

    如果有的话,在脚本输入包含非ASCII值的情况下,我可能希望eval版本在没有use utf8的情况下中断。 (进一步测试表明,将非ASCII值传递给bar()确实会导致eval失败并出现相同的错误)

  3. <小时/> 请注意,许多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;我知道该怎么做。我很好奇为什么它首先似乎是必要的。

2 个答案:

答案 0 :(得分:4)

在失败的验证中,你正在执行

$re = ''.qr/\b($re)\b/i

在成功的版本中,您正在执行

$re = ''.qr/\b(foo)\b/i

当模式被编译为Unicode模式(无论这意味着什么)时,听起来像qr //需要utf8.pm,但后者不会编译为Unicode模式。


无法加载utf8.pm是由于plperl创建的Safe隔离区施加的限制。

修复方法是将模块加载到安全隔间外。

解决方法是使用效率更高的

$re = '(?^u:\\b(?i:'.$re.')\\b)';

答案 1 :(得分:0)

我有同样的问题,我通过添加

修复了它
username.github.io/project_name

plperl.on_init = 'use utf8; use re; package utf8; require "utf8_heavy.pl";' 档。

我希望这会对某人有所帮助。