2013-12-03 2 views
4

Я столкнулся с особенностью хранимой процедуры plperl на Postgres 9.2 с Perl 5.12.4.Почему эта хранимая процедура postgres хочет использовать utf8?

Любопытное поведение может быть воспроизведена с помощью этого "сломанный" 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.

    Во всяком случае, я мог ожидать, что версия eval разрывается без use utf8, в случае, если входные данные для скрипта содержат значения, отличные от ASCII. (Дальнейшее тестирование показывает, что передача значений не-ASCII преградить() действительно вызывает Eval на неудачу с такой же ошибкой)


Обратите внимание, что многие Postgres установки автоматической загрузки «utf8» при запуске на Perl переводчик. Это значение по умолчанию в Debian, по крайней мере, как показано на выполнение DO 'elog(WARNING, join ", ", sort keys %INC)' language plperl;:

ВНИМАНИЕ: Carp.pm, карп/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, перегрузка.pm, strict.pm, vars.pm, warnings.pm, warnings/register.pm
КОНТЕКСТ: PL/Perl анонимный блок кода
DO

Этот вопрос не о том, как получить свою целевую машину для загрузки utf8 автоматически; Я знаю, как это сделать. Мне любопытно, почему это, по-видимому, необходимо в первую очередь.

+0

(Не работает, потому что вы забыли избежать '' '. Вы также должны избежать второго' $ '.) – ikegami

+0

@ikegami: Второй' $ 'не должен быть экранирован, но хороший вызов на' \ 'chars; теперь я получаю правильный вывод, что делает вопрос еще более загадочным. – Flimzy

+0

Да, должно. Если вы не избежите второго '$', он будет терпеть неудачу для '$ re = '/; система («rm -rf /»); дг/';'. Ошибка впрыска! – ikegami

ответ

4

В verison, что это упущение, вы выполнение

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

В версии, которая последующая, вы выполнение

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

Похоже квартером // нужен utf8.pm когда шаблон был скомпилирован как шаблон Unicode (независимо от того, что это означает), но последний не скомпилирован как шаблон Unicode.


Неисправность utf8.pm связана с ограничениями, налагаемыми отсеком Safe, созданным plperl.

Исправление заключается в загрузке модуля за пределы отсека для безопасного использования.

Обойти является использование более эффективным

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

Думаю, вы ответили на вопрос; хотя ваш рабочий процесс действительно не работает, поскольку он не делает то же самое. – Flimzy

+0

@Flimzy, Исправлено. – ikegami

+0

Нет, это то же самое, даже если '$ re = qr/foo/i;' или '$ re = '/ foo/i';'. (Не уверен, какой из них вы имели в виду.) Единственное различие, которое приходит в голову, это то, что он не умрет, если шаблон в '$ re' является незаконным. – ikegami

0

Я была такая же проблема, и я установил его, добавив

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

в postgresql.conf файл.

Надеюсь, это поможет кому-то.

Смежные вопросы