Home > Back-end >  DBD::Firebird encoding/decoding
DBD::Firebird encoding/decoding

Time:06-16

In this example, Firebird returns the string undecoded. Have I not set up the database correctly or is this how Firebird works?

#!/usr/bin/env perl
use warnings;
use 5.10.0;
use utf8;
use open qw( :std :utf8 );
use Devel::Peek;
use DBI;

my ( $db, $dbh, $sth, @array );
my $table = 'test_encoding';
my $create = "CREATE TABLE $table ( name varchar(32) )";
my $insert = "INSERT INTO $table ( name ) VALUES ( ? )";
my $select = "SELECT * FROM $table";
my $value = 'ä';

$db = '/home/me/my_firebird_db';
$dbh = DBI->connect(
    "dbi:Firebird:db=$db", 'user', 'password',
    { PrintError => 0, RaiseError => 1, ib_charset => 'UTF-8' }
);
$sth = $dbh->do( "DROP TABLE $table" );
$sth = $dbh->do( $create );;
$sth = $dbh->prepare( $insert );
$sth->execute( $value );
@array = $dbh->selectrow_array( $select );
Dump $array[0];
say $array[0];
say "";

$db = '/home/me/my_sqlite_db';
$dbh = DBI->connect(
    "dbi:SQLite:db=$db", '', '',
    { PrintError => 0, RaiseError => 1, sqlite_string_mode => 5 }
);
$sth = $dbh->do( "DROP TABLE IF EXISTS $table" );
$sth = $dbh->do( $create );
$sth = $dbh->prepare( $insert );
$sth->execute( $value );
@array = $dbh->selectrow_array( $select );
Dump $array[0];
say $array[0];

Output:

SV = PV(0x2105360) at 0x22628a0
  REFCNT = 1
  FLAGS = (POK,pPOK)
  PV = 0x22a37e0 "\303\244"\0
  CUR = 2
  LEN = 10
ä

SV = PV(0x2111470) at 0x2121220
  REFCNT = 1
  FLAGS = (POK,pPOK,UTF8)
  PV = 0x1f2fed0 "\303\244"\0 [UTF8 "\x{e4}"]
  CUR = 2
  LEN = 10
ä

CodePudding user response:

As indicated by the link to the documentation of DBD::Firebird supplied by clamp in the comments, you need to connect using:

$dbh = DBI->connect(
    "dbi:Firebird:db=$db;ib_charset=UTF8", 'user', 'password',
    { PrintError => 0, RaiseError => 1, ib_enable_utf8 => 1 }

That is, the ib_charset property must be in the connection string, not in the hash, and its value must be UTF8 (not UTF-8!), and you need to add ib_enable_utf8 with setting 1 to the hash.

Specifically, this part:

ib_enable_utf8 (driver-specific, boolean)

Setting this attribute to TRUE will cause any Perl Unicode strings supplied as statement parameters to be downgraded to octet sequences before passing them to Firebird.

Also, any character data retrieved from the database (CHAR, VARCHAR, BLOB sub_type TEXT) will be upgraded to Perl Unicode strings.

Caveat: Currently this is supported only if the ib_charset DSN parameter is UTF8. In the future, encoding and decoding to/from arbitrary character set may be implemented.

Example:

$dbh = DBI->connect( 'dbi:Firebird:db=database.fdb;ib_charset=UTF8',
    { ib_enable_utf8 => 1 } );
  • Related