On Tuesday 12 September 2017 12:27:25 p...@cpan.org wrote:
> To prove fact that other DBI drivers (e.g. Pg or SQLite) had fixed
> similar/same UTF-8 issue as MySQL has and behave Perl-correctly, I
> would provide test cases so you would see difference between Pg,
> SQLite and mysql DBI drivers.

And here is promised script:

=======================================

use strict;
use warnings;
use utf8;
binmode \*STDOUT, ':utf8';
binmode \*STDERR, ':utf8';
use DBI;

sub ords { $_[0] . ' (' . (join ', ', map ord, split //, $_[0]) . ')' }

# DBD::Pg enables Unicode <--> UTF-8 automatically
my $pg_dbh = DBI->connect("dbi:Pg:dbname=postgres", "", "");

# DBD::mysql needs mysql_enable_utf8 and mysql_enable_utf8mb4 for Unicode <--> 
UTF-8
my $mysql_dbh = DBI->connect("dbi:mysql:dbname=mysql", "root", "", { 
mysql_enable_utf8 => 1, mysql_enable_utf8mb4 => 1 });
# MySQL server by default uses latin1
# Without switch to utf8mb4, Unicode code points above U+FF cannot be stored (á 
is below U+FF, č not)
# Another option is to specify own charset in CREATE TABLE
$mysql_dbh->do("SET character_set_database='utf8mb4'");
$mysql_dbh->do("SET character_set_server='utf8mb4'");

# DBD::SQLite needs sqlite_unicode for Unicode <--> UTF-8
my $sqlite_dbh = DBI->connect("dbi:SQLite:dbname=:memory:", "", "", { 
sqlite_unicode => 1 });

for my $dbh ($pg_dbh, $mysql_dbh, $sqlite_dbh) {
  for my $ins ("\xC3\xA1", "\N{U+C3}\N{U+A1}", "á", "č", "\x{263A}", 
"\N{U+263A}", "☺") {
    {
      $dbh->do("CREATE TEMPORARY TABLE t(s VARCHAR(10))");
      my $sth = $dbh->prepare("INSERT INTO t(s) VALUES('$ins')");
      $sth->execute();
      my $fetch = $dbh->selectrow_array("SELECT s FROM t");
      print $dbh->{Driver}->{Name} . ' without bind - insert: ' . ords($ins) . 
'; fetch: ' . ords($fetch) . ' - ' . ($ins eq $fetch ? 'OK' : 'FAIL') . "\n";
      $dbh->do("DROP TABLE t");
    }
    {
      $dbh->do("CREATE TEMPORARY TABLE t(s VARCHAR(10))");
      my $sth = $dbh->prepare("INSERT INTO t(s) VALUES(?)");
      $sth->execute($ins);
      my $fetch = $dbh->selectrow_array("SELECT s FROM t");
      print $dbh->{Driver}->{Name} . ' with bind - insert: ' . ords($ins) . '; 
fetch: ' . ords($fetch) . ' - ' . ($ins eq $fetch ? 'OK' : 'FAIL') . "\n";
      $dbh->do("DROP TABLE t");
    }
  }
}

=======================================

It is simple "identity" script, which stores value into database,
fetches it back and then compare results.

Look on results with DBD::mysql 4.041, 4.042 and 4.043.
Are all users of DBD::mysql aware of such results?

And specially look at results with DBD::Pg prior to version 3.3.0 and up.
Also DBD::SQLite prior to version 1.43_04.

Basically DBD::Pg (pg_enable_utf8 = -1) and DBD::SQLite
(via sqlite_unicode=1) had exactly same bug as DBD::mysql.

Reply via email to