Обработка текста в кодировке UTF8 в SQLite с использованием Rose::DB::Object

Я использую Rose:: DB:: Object, SQLite и китайский текст. Мои занятия выглядят так:

package My::DB;

use base qw(Rose::DB);

__PACKAGE__->use_private_registry;

__PACKAGE__->register_db(
  driver   => 'sqlite',
  database => 'data/sqmple.db',
);

package Motorcycle;

use My::DB;

use base qw(Rose::DB::Object); 
...
sub init_db { My::DB->new() };

Код, используемый для хранения записи:

Motorcycle->new(
  type  => $self->param('type'),
  brand => $self->param('brand'),
  color => $self->param('color'),
)->save;

Код, используемый для отображения данных (из приложения Mojolicious):

<td><%= Mojo::ByteStream->new($cycle->type)->decode("utf-8") %></td>
<td><%= Mojo::ByteStream->new($cycle->brand)->decode("utf-8") %></td>
<td><%= Mojo::ByteStream->new($cycle->color)->decode("utf-8") %></td>

Как я могу исключить этап декодирования? Я хотел бы, чтобы код дисплея выглядел так:

<td><%= $cycle->type %></td>
<td><%= $cycle->brand %></td>
<td><%= $cycle->color %></td>

2 ответа

Решение

Я думаю, вам нужно получить sqlite_unicode => 1 Значение конфигурации вплоть до SQLite, был похожий вопрос о UTF-8 и SQLite, настройка sqlite_unicode сделал трюк там.

Я не думаю, что Rose:: DB:: SQLite поддерживает этот параметр конфигурации, хотя. Исходя из этой, возможно, похожей проблемы с MySQL, вы можете исправить патч Rose:: DB:: SQLite для добавления поддержки sqlite_unicode добавив это в драйвер:

sub sqlite_unicode {
{
  shift->dbh_attribute_boolean('sqlite_unicode', @_)
}

Я оставлю комментарий к ответу Джона, чтобы он смог проверить это.

Если это сработает, возможно, вы захотите отправить патч Джону Сиракузе (который уже не только по этому вопросу, но и сопровождающему Rose:: DB).

Если вы подаете текст в кодировке UTF8 в SQLite, он должен вернуть его вам в той же форме. Например, для базы данных SQLite с именем test.db, содержащей эту схему:

CREATE TABLE things
(
  id   INTEGER PRIMARY KEY AUTOINCREMENT,
  name VARCHAR(64) NOT NULL
);

Запустите этот код в сценарии в том же каталоге, что и база данных test.db:

package My::DB;

use base qw(Rose::DB);

__PACKAGE__->use_private_registry;

__PACKAGE__->register_db
(
  driver   => 'sqlite',
  database => 'test.db',
);

package My::Thing;

use base qw(Rose::DB::Object); 

__PACKAGE__->meta->setup
(
  table   => 'things',
  columns =>
  [
    id   => { type => 'serial', primary_key => 1, not_null => 1 },
    name => { type => 'text', length => 64, not_null => 1 },
  ],
);

sub init_db { My::DB->new }

package main;

# Set the name to a UTF8-encoded smiley: Unicode 0x263A
my $thing = My::Thing->new(name => "\x{e2}\x{98}\x{ba}")->save; 

$thing = My::Thing->new(id => $thing->id)->load;

# This will print the UTF8-encoded smiley; make sure your
# terminal can handle UTF8 output.
print $thing->name, "\n";

Если это не работает для вас, то, возможно, ваши звонки, чтобы получить параметры формы (например, $self->param('type')) возвращают символьные строки вместо строк в кодировке UTF8. То есть в случае смайлика, возможно, $self->param('foo') возвращает "\x{263a}", а не "\x{e2}\x{98}\x{ba}". В этом случае решением было бы закодировать строки как UTF8 перед установкой атрибутов объекта:

Motorcycle->new(
  type  => utf8::encode($self->param('type')),
  brand => utf8::encode($self->param('brand')),
  color => utf8::encode($self->param('color')),
)->save;
Другие вопросы по тегам