Skip to content

Commit 02a3357

Browse files
Add test for Japanese characters in table definition and errors
The tests are taken from DBD::MariaDB and adopted to DBD::mysql. There are two test files: * one for testing of utf8/utf8mb4 identifiers * one for testing of utf8 error messages There are three runs of all tests in both test files: * one without mysql_enable_utf8 option * one with enabled mysql_enable_utf8 option * one with enabled mysql_enable_utf8mb4 option There are XXX comments for situations which not follow mysql_enable_utf8/mb4 option.
1 parent f9eab6a commit 02a3357

File tree

3 files changed

+240
-0
lines changed

3 files changed

+240
-0
lines changed

MANIFEST

+2
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ t/51bind_type_guessing.t
5353
t/52comment.t
5454
t/53comment.t
5555
t/55utf8.t
56+
t/55utf8_errors.t
57+
t/55utf8_identifiers.t
5658
t/55utf8mb4.t
5759
t/56connattr.t
5860
t/57trackgtid.t

t/55utf8_errors.t

+111
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
use strict;
2+
use warnings;
3+
4+
use Test::More;
5+
use DBI;
6+
use Encode;
7+
8+
use vars qw($test_dsn $test_user $test_password);
9+
use lib 't', '.';
10+
require "lib.pl";
11+
12+
sub skip_rt_102404 {
13+
skip "(Perl 5.13.1 and DBI 1.635) or DBI 1.639 is required due to bug RT 102404", $_[0] unless ($] >= 5.013001 and eval { DBI->VERSION(1.635) }) or eval { DBI->VERSION(1.639) };
14+
}
15+
16+
my $dbh;
17+
eval {
18+
$dbh = DBI->connect($test_dsn, $test_user, $test_password,
19+
{ RaiseError => 1, PrintError => 1, AutoCommit => 0 });
20+
};
21+
if ($@) {
22+
plan skip_all => "no database connection";
23+
}
24+
$dbh->disconnect();
25+
26+
plan tests => 10 * 3;
27+
28+
# All in internal Perl Unicode
29+
my $jpnErr = qr/\x{4ed8}\x{8fd1}.*\x{884c}\x{76ee}/; # Use \x{...} instead \N{U+...} due to Perl 5.12.0 bug
30+
31+
foreach my $mysql_enable_utf8 (0, 1, 2) {
32+
my %utf8_params = ();
33+
if ($mysql_enable_utf8 == 1) {
34+
$utf8_params{'mysql_enable_utf8'} = 1;
35+
diag "Enabled mysql_enable_utf8.";
36+
# XXX There are no utf8mb4 error characters
37+
} elsif ($mysql_enable_utf8 == 2) {
38+
$utf8_params{'mysql_enable_utf8mb4'} = 1;
39+
diag "Enabled mysql_enable_utf8mb4.";
40+
} else {
41+
diag "Disabled mysql_enable_utf8.";
42+
}
43+
$dbh = DBI->connect($test_dsn, $test_user, $test_password,
44+
{ RaiseError => 1, PrintError => 1, AutoCommit => 1, %utf8_params });
45+
46+
eval {
47+
$dbh->do("SET lc_messages = 'ja_JP'");
48+
} or do {
49+
$dbh->disconnect();
50+
plan skip_all => "Server lc_messages ja_JP are needed for this test";
51+
};
52+
53+
my $sth;
54+
my $warn;
55+
my $dieerr;
56+
my $dbierr;
57+
my $failed;
58+
59+
$failed = 0;
60+
$dieerr = undef;
61+
$dbierr = undef;
62+
$dbh->{HandleError} = sub { $dbierr = $_[0]; die $_[0]; };
63+
eval {
64+
$sth = $dbh->prepare("foo");
65+
$sth->execute();
66+
1;
67+
} or do {
68+
$dieerr = $@;
69+
$failed = 1;
70+
};
71+
$dbh->{HandleError} = undef;
72+
73+
ok($failed, 'Execution of bad statement is failing (HandleError version).');
74+
like(Encode::decode('UTF-8', $dbierr), $jpnErr, 'DBI error is in octets (HandleError version).'); # XXX
75+
like(Encode::decode('UTF-8', $DBI::errstr), $jpnErr, 'DBI::errstr is in octets (HandleError version).'); # XXX
76+
like(Encode::decode('UTF-8', $dbh->errstr), $jpnErr, 'DBI handler errstr() method is in octets (HandleError version).'); # XXX
77+
78+
SKIP : {
79+
skip_rt_102404 1;
80+
like(Encode::decode('UTF-8', $dieerr), $jpnErr, 'Error from eval is in octets (HandleError version).');
81+
}
82+
83+
$failed = 0;
84+
$warn = undef;
85+
$dieerr = undef;
86+
$dbh->{PrintError} = 1;
87+
$SIG{__WARN__} = sub { $warn = $_[0] };
88+
eval {
89+
$sth = $dbh->prepare("foo");
90+
$sth->execute();
91+
1;
92+
} or do {
93+
$dieerr = $@;
94+
$failed = 1;
95+
};
96+
$dbh->{PrintError} = 0;
97+
$SIG{__WARN__} = 'DEFAULT';
98+
99+
ok($failed, 'Execution of bad statement is failing (PrintError version).');
100+
like(Encode::decode('UTF-8', $DBI::errstr), $jpnErr, 'DBI::errstr is in octets (PrintError version).'); # XXX
101+
like(Encode::decode('UTF-8', $dbh->errstr), $jpnErr, 'DBI handler errstr() method is in octets (PrintError version).'); # XXX
102+
103+
SKIP : {
104+
skip_rt_102404 2;
105+
like(Encode::decode('UTF-8', $warn), $jpnErr, 'Warning is in octets (PrintError version).'); # XXX
106+
like(Encode::decode('UTF-8', $dieerr), $jpnErr, 'Error from eval is in octets (PrintError version).'); # XXX
107+
}
108+
109+
$dbh->disconnect();
110+
}
111+
done_testing;

t/55utf8_identifiers.t

+127
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
use strict;
2+
use warnings;
3+
4+
use Test::More;
5+
use DBI;
6+
use Encode;
7+
8+
use vars qw($test_dsn $test_user $test_password);
9+
use lib 't', '.';
10+
require "lib.pl";
11+
12+
sub for_db {
13+
my ($mysql_enable_utf8, $value) = @_; # Value is in internal Perl Unicode.
14+
15+
my $ret;
16+
if ($mysql_enable_utf8 >= 1) {
17+
$ret = $value;
18+
} else {
19+
$ret = Encode::encode('UTF-8', $value);
20+
}
21+
22+
return $ret;
23+
}
24+
25+
my $dbh;
26+
eval {
27+
$dbh = DBI->connect($test_dsn, $test_user, $test_password,
28+
{ RaiseError => 1, PrintError => 1, AutoCommit => 0 });
29+
};
30+
if ($@) {
31+
plan skip_all => "no database connection";
32+
}
33+
$dbh->disconnect();
34+
35+
plan tests => 11 * 3 + 11 * 2;
36+
37+
# All in internal Perl Unicode
38+
my $jpnTable = "\N{U+8868}"; # Japanese table
39+
my $jpnColumn = "\N{U+6027}\N{U+5225}"; # Japanese column - word "gender"
40+
my $jpnData1 = "\N{U+5c71}\N{U+7530}\N{U+592a}\N{U+90ce}"; # Japanese data - person name
41+
my $jpnData2 = "\N{U+7537}"; # Japanese daya - word "male"
42+
my $chiTable = "\N{U+5927}\N{U+99AC}"; # Chinese table XXX MySQL doesn't support utf8mb4 in table names
43+
my $chiColumn = "\N{U+5C0F}\N{U+96EA}\N{U+4EBA}"; # Chinese column XXX MySQL doesn't support utf8mb4 in column names
44+
my $chiData1 = "\N{U+30001}"; # Chinese data
45+
my $chiData2 = "\N{U+30002}"; # Chinese data
46+
47+
foreach my $mysql_enable_utf8 (0, 1, 2) {
48+
my %utf8_params = ();
49+
if ($mysql_enable_utf8 == 1) {
50+
$utf8_params{'mysql_enable_utf8'} = 1;
51+
diag "Enabled mysql_enable_utf8.";
52+
} elsif ($mysql_enable_utf8 == 2) {
53+
$utf8_params{'mysql_enable_utf8mb4'} = 1;
54+
diag "Enabled mysql_enable_utf8mb4.";
55+
} else {
56+
diag "Disabled mysql_enable_utf8.";
57+
}
58+
$dbh = DBI->connect($test_dsn, $test_user, $test_password,
59+
{ RaiseError => 1, PrintError => 1, AutoCommit => 1, %utf8_params });
60+
61+
my $jpnTable_db = for_db($mysql_enable_utf8, $jpnTable);
62+
my $jpnColumn_db = for_db($mysql_enable_utf8, $jpnColumn);
63+
my $jpnData1_db = for_db($mysql_enable_utf8, $jpnData1);
64+
my $jpnData2_db = for_db($mysql_enable_utf8, $jpnData2);
65+
my ($chiTable_db, $chiColumn_db, $chiData1_db, $chiData2_db);
66+
if ($mysql_enable_utf8 == 0 || $mysql_enable_utf8 == 2) {
67+
$chiTable_db = for_db($mysql_enable_utf8, $chiTable);
68+
$chiColumn_db = for_db($mysql_enable_utf8, $chiColumn);
69+
$chiData1_db = for_db($mysql_enable_utf8, $chiData1);
70+
$chiData2_db = for_db($mysql_enable_utf8, $chiData2);
71+
}
72+
73+
my $sth;
74+
my $row;
75+
76+
ok($dbh->do("DROP TABLE IF EXISTS $jpnTable_db"), 'Drop table for Japanese testing.');
77+
if ($mysql_enable_utf8 == 0 || $mysql_enable_utf8 == 2) {
78+
ok($dbh->do("DROP TABLE IF EXISTS $chiTable_db"), 'Drop table for Chinese testings.');
79+
}
80+
81+
ok($dbh->do(<<"END"
82+
CREATE TABLE IF NOT EXISTS $jpnTable_db (
83+
name VARCHAR(20),
84+
$jpnColumn_db CHAR(1)
85+
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin
86+
END
87+
), 'Create temporay table with Japanese characters.');
88+
if ($mysql_enable_utf8 == 0 || $mysql_enable_utf8 == 2) {
89+
ok($dbh->do(<<"END"
90+
CREATE TABLE IF NOT EXISTS $chiTable_db (
91+
name VARCHAR(20),
92+
$chiColumn_db CHAR(1)
93+
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin
94+
END
95+
), 'Create temporay table with Chinese characters.');
96+
}
97+
98+
ok($sth = $dbh->prepare("INSERT INTO $jpnTable_db (name, $jpnColumn_db) VALUES (?, ?)"), 'Prepare insert statement with Japanese values.');
99+
ok($sth->execute($jpnData1_db, $jpnData2_db), 'Execute insert statement with Japanese values.');
100+
if ($mysql_enable_utf8 == 0 || $mysql_enable_utf8 == 2) {
101+
ok($sth = $dbh->prepare("INSERT INTO $chiTable_db (name, $chiColumn_db) VALUES (?, ?)"), 'Prepare insert statement with Chinese values.');
102+
ok($sth->execute($chiData1_db, $chiData2_db), 'Execute insert statement with Chinese values.');
103+
}
104+
105+
ok($sth = $dbh->prepare("SELECT * FROM $jpnTable_db"), 'Prepare select statement with Japanese values.');
106+
ok($sth->execute(), 'Execute select statement with Japanese values.');
107+
ok($row = $sth->fetchrow_hashref(), 'Fetch hashref with Japanese values.');
108+
is($row->{name}, $jpnData1_db, "Japanese value.");
109+
ok(!exists $row->{$jpnColumn}, 'Not exists Japanese key in internal Perl Unicode.'); # XXX
110+
is($row->{Encode::encode('UTF-8', $jpnColumn)}, $jpnData2_db, 'Exists Japanese key in octets and value.'); # XXX
111+
is_deeply($sth->{NAME}, [ 'name', Encode::encode('UTF-8', $jpnColumn) ], 'Statement Japanese column name is in octets.'); # XXX
112+
is_deeply($sth->{mysql_table}, [ Encode::encode('UTF-8', $jpnTable), Encode::encode('UTF-8', $jpnTable) ], 'Statement Japanese table name is in octets.'); # XXX
113+
if ($mysql_enable_utf8 == 0 || $mysql_enable_utf8 == 2) {
114+
ok($sth = $dbh->prepare("SELECT * FROM $chiTable_db"), 'Prepare select statement with Chinese values.');
115+
ok($sth->execute(), 'Execute select statement with Chinese values.');
116+
ok($row = $sth->fetchrow_hashref(), 'Fetch hashref with Chinese values.');
117+
is($row->{name}, $chiData1_db, "Chinese value.");
118+
ok(!exists $row->{$chiColumn}, 'Not exists Chinese key in internal Perl Unicode.'); # XXX
119+
is($row->{Encode::encode('UTF-8', $chiColumn)}, $chiData2_db, 'Exists Chinese key in octets and value.'); # XXX
120+
is_deeply($sth->{NAME}, [ 'name', Encode::encode('UTF-8', $chiColumn) ], 'Statement Chinese column name is in octets.'); # XXX
121+
is_deeply($sth->{mysql_table}, [ Encode::encode('UTF-8', $chiTable), Encode::encode('UTF-8', $chiTable) ], 'Statement Chinese table name is in octets.'); # XXX
122+
}
123+
124+
$sth->finish();
125+
$dbh->disconnect();
126+
}
127+
done_testing;

0 commit comments

Comments
 (0)