LINUX.ORG.RU

PgPerl и utf8

 , ,


0

2

В таблице с локалью ru.Utf8 есть русские буквы. Из функции pgPerl хочу вернуть значения из этой таблицы русскими буквами.

Получаю я вроде как utf8 (судя по utf8::is_utf8), но вот отображается оно «иероглифами ».

Как быть? Как получить нормальный результат?

★★★★★

Последнее исправление: bvn13 (всего исправлений: 1)

А если результат функции Data::Dumper'ом напечатать, он покажет символы вида \x{...} с кодом больше ff?

AITap ★★★★★
()
Ответ на: комментарий от AITap

через elog кажут:

ИНФОРМАЦИЯ:  name_ru is UTF8: 1
ИНФОРМАЦИЯ:  DUMPER: $VAR1 = "* \x{43d}\x{435}\x{434}\x{43e}\x{441}\x{442}\x{443}\x{43f}\x{43d}\x{43e}";

bvn13 ★★★★★
() автор топика
Ответ на: комментарий от bvn13
$ perl -CSD -E'say "* \x{43d}\x{435}\x{434}\x{43e}\x{441}\x{442}\x{443}\x{43f}\x{43d}\x{43e}";'
* недоступно

Данные поступают в форме внутреннего представления Perl'ом символов. Похоже, что что-то об этом не догадывается и при показе результатов запроса второй раз кодирует их (почему-то из latin1).

Возможно, перед возвратом имеет смысл кодировать их в кодировку таблицы (в байты):

use Encode 'encode';
...;
return encode utf8 => $mydata;

AITap ★★★★★
()
Ответ на: комментарий от AITap

Я пробовал так.

elog(INFO, "" . $row->{id} . "name_ru is UTF8: " . utf8::is_utf8($row->{name_ru}));
#Encode::_utf8_on($row->{name_ru});
#elog(INFO, "" . $row->{id} . "name_ru is UTF8: " . utf8::is_utf8($row->{name_ru}));
elog(INFO, "DUMPER: " . Dumper Encode::encode('utf8',$row->{name_ru}));

(и флаг включить, и перекодировать в утф)

результат тот же.

bvn13 ★★★★★
() автор топика
Ответ на: комментарий от AITap

Хм... я тут еще раскопал.

Для вывода результата я использую Mojo::JSON, в которой заявлена полная поддержка utf8. Если я без нее просто верну строку, содержащую русские буквы, то все нормально, все отображается ровно. А с этим JSON-ом нет. Не подскажете, как быть?

bvn13 ★★★★★
() автор топика
Ответ на: комментарий от AITap

Но в простом примере этот Mojo::JSON нормально отрабатывает:

> cat 1.pl && perl 1.pl
#!/usr/bin/perl

use strict;
use warnings;

use utf8;

use Mojo::JSON;


print Mojo::JSON->new->encode(
    {
        test => 'тест'
    }
);

РЕЗУЛЬТАТ:
{"test":"тест"}

bvn13 ★★★★★
() автор топика
Ответ на: комментарий от bvn13

Mojo::JSON возвращает байты. Поэтому когда требуется получить utf8 строку приходится делать так

my $json = Mojo::JSON->new->encode($ref);
utf8::decode($json);

Olegymous ★★★
()
Ответ на: комментарий от AITap

Нет. Мне это определенно не нравится.

Сейчас вот так:

my $res = {
    objects => []
};

my $q = "SELECT * FROM mgdata.objects_catalog";
my $rv = spi_exec_query($q);
if ($rv->{error}) {
    elog(ERROR, "QUERY: $q\nERROR: $@\n");
    return '{"objects":"error"}';
}

for my $row (@{$rv->{rows}}) {
    push $res->{objects}, 
    {
        id => $row->{id},
        name => $row->{name},
        name_ru => $row->{name_ru},
        area_x => $row->{area_x},
        area_y => $row->{area_y},
        available_level => $row->{available_level}
    };
}

return Mojo::JSON->new->encode($res);

При этом результат в приложении получаю такой:

 {
                                                            'area_y' => '1',
                                                            'area_x' => '1',
                                                            'name' => '* unavailable',
                                                            'id' => '1',
                                                            'available_level' => '0',
                                                            'name_ru' => "* \x{c3}\x{83}\x{c2}\x{90}\x{c3}\x{82}\x{c2}\x{bd}\x{c3}\x{83}\x{c2}\x{90}\x{c3}\x{82}\x{c2}\x{b5}\x{c3}\x{83}\x{c2}\x{90}\x{c3}\x{82}\x{c2}\x{b4}\x{c3}\x{83}\x{c2}\x{90}\x{c3}\x{82}\x{c2}\x{be}\x{c3}\x{83}\x{c2}\x{91}\x{c3}\x{82}\x{c2}\x{81}\x{c3}\x{83}\x{c2}\x{91}\x{c3}\x{82}\x{c2}\x{82}\x{c3}\x{83}\x{c2}\x{91}\x{c3}\x{82}\x{c2}\x{83}\x{c3}\x{83}\x{c2}\x{90}\x{c3}\x{82}\x{c2}\x{bf}\x{c3}\x{83}\x{c2}\x{90}\x{c3}\x{82}\x{c2}\x{bd}\x{c3}\x{83}\x{c2}\x{90}\x{c3}\x{82}\x{c2}\x{be}"
}

Но это как бы:

> perl -CSD -E'say  "* \x{c3}\x{83}\x{c2}\x{90}\x{c3}\x{82}\x{c2}\x{bd}\x{c3}\x{83}\x{c2}\x{90}\x{c3}\x{82}\x{c2}\x{b5}\x{c3}\x{83}\x{c2}\x{90}\x{c3}\x{82}\x{c2}\x{b4}\x{c3}\x{83}\x{c2}\x{90}\x{c3}\x{82}\x{c2}\x{be}\x{c3}\x{83}\x{c2}\x{91}\x{c3}\x{82}\x{c2}\x{81}\x{c3}\x{83}\x{c2}\x{91}\x{c3}\x{82}\x{c2}\x{82}\x{c3}\x{83}\x{c2}\x{91}\x{c3}\x{82}\x{c2}\x{83}\x{c3}\x{83}\x{c2}\x{90}\x{c3}\x{82}\x{c2}\x{bf}\x{c3}\x{83}\x{c2}\x{90}\x{c3}\x{82}\x{c2}\x{bd}\x{c3}\x{83}\x{c2}\x{90}\x{c3}\x{82}\x{c2}\x{be}";'
* ���½���µ���´���¾���������������¿���½���¾

bvn13 ★★★★★
() автор топика

В таблице с локалью ru.Utf8 есть русские буквы. Из функции pgPerl хочу вернуть значения из этой таблицы русскими буквами.

Вангую, что у вас кодировка соединения с постгресом latin1.

no-such-file ★★★★★
()
Ответ на: комментарий от Olegymous

Вот спасибо! Сделал возврат из ПГ-функции так:

return Encode::decode('utf8',Mojo::JSON->new->encode($res));

Стало в пгАдмине видно нормально.

Теперь хоть понятней, куда копать и как преобразовывать.

bvn13 ★★★★★
() автор топика

Минувшим летом мигрировал на свежий постгрес и юникод. Очень просто решился вопрос.

Прежде всего

$dbh->{'pg_enable_utf8'} = 1;

outtaspace ★★★
()
Ответ на: комментарий от bvn13

\x{c3}\x{83}...

Это байты, декодированные как символы latin1. Внутри - UTF-8, подвергшийся конвертации из latin1 в UTF-8.

А прочитать его удалось вот так:

$ perl -E'
my $i = "* \x{c3}\x{83}\x{c2}\x{90}\x{c3}\x{82}\x{c2}\x{bd}\x{c3}\x{83}\x{c2}\x{90}\x{c3}\x{82}\x{c2}\x{b5}\x{c3}\x{83}\x{c2}\x{90}\x{c3}\x{82}\x{c2}\x{b4}\x{c3}\x{83}\x{c2}\x{90}\x{c3}\x{82}\x{c2}\x{be}\x{c3}\x{83}\x{c2}\x{91}\x{c3}\x{82}\x{c2}\x{81}\x{c3}\x{83}\x{c2}\x{91}\x{c3}\x{82}\x{c2}\x{82}\x{c3}\x{83}\x{c2}\x{91}\x{c3}\x{82}\x{c2}\x{83}\x{c3}\x{83}\x{c2}\x{90}\x{c3}\x{82}\x{c2}\x{bf}\x{c3}\x{83}\x{c2}\x{90}\x{c3}\x{82}\x{c2}\x{bd}\x{c3}\x{83}\x{c2}\x{90}\x{c3}\x{82}\x{c2}\x{be}";
say decode utf8 => decode(latin1 => decode( utf8 => $i));' 
* недоступно

Судя по http://search.cpan.org/~jsiracusa/Rose-DB-0.770/lib/Rose/DB/Pg.pm, Вам нужен метод pg_enable_utf8 объекта Rose::DB::Pg, как и советовали выше.

AITap ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.