5

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//操作を評価に移動すると、機能します。

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 ではありませ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 を自動的にロードさせる方法に関するものではありません。私はそれを行う方法を知っています。そもそもなぜ必要なのか気になります。

4

2 に答える 2

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)';
于 2013-12-03T15:56:53.627 に答える