DBD-MariaDB
view release on metacpan or search on metacpan
- Fix setting client_flag for mysql_real_connect()
- Fix calling DBI->data_sources() without second argument
- Fix $dbh->last_insert_id() for multi and prepared server side statements
- Use dbd_db_do6 API from DBI 1.642 when available
- Add support for a new DBI method call $sth->last_insert_id()
- Add sanity check for Makefile.PL --testsocket, --testhost and --testport
- Report error when $dbh->{mariadb_ssl_cipher} attribute is not supported
- Check that correct number of bind parameters are in $dbh->do()
- Update workarounds for bugs in MariaDB client library (some were fixed)
- Allow to set zero read, write and connect timeout (which means infinite)
- Set default session collation to utf8mb4_unicode_ci for real Unicode
- Change minimal MySQL client version to 4.1.8 (older is incompatible)
- Skip tests which cannot be started on current system/architecture
- Move testrules.yml to t/ directory
- Miscellaneous fixes in tests
1.00 2018-07-12
- Do not remove test name and line from test error messages
- Update documentation for mariadb_length and mariadb_max_length
- Fix retrieving ODBC attribute SQL_USER_NAME via $dbh->get_info()
- Do not show internal DBI packages on cpan
Changes.historic view on Meta::CPAN
2013-04-12 Patrick Galbraith et open source community <patg at patg dot net> (4.023)
Fix memory leak if mysql_server_prepare is enabled.
* Fix primary_key_info result ordering - https://github.com/CaptTofu/DBD-mysql/pull/39 - Dagfinn Ilmari Mannsåker
* allow compilation with msvc - https://github.com/CaptTofu/DBD-mysql/pull/37 - Walde Christian
* just to set MYSQL_OPT_WRITE_TIMEOUT and MYSQL_OPT_READ_TIMEOUT by dsn - https://github.com/CaptTofu/DBD-mysql/pull/36 - Naosuke Yokoe
* just remove unnecessary "my" - https://github.com/CaptTofu/DBD-mysql/pull/34 - Shoichi Kaji
* eval $ExtUtils::MakeMaker::VERSION requires for old ExtUtils::MakeMaker - https://github.com/CaptTofu/DBD-mysql/pull/32 - Daisuke Murase
* Updated documentation to reflect that bugs will be reported at rt.cpan.org
* Updated version
* Chased tail finding issue with -1 being converted to max unsigned int in PS mode
* Various typos and other unicode fixes dsteinbrunner <dsteinbrunner@gmail.com>
* Fixed permissions on files.
* Clarified documentation and bumped version for next release
2012-08-28 Patrick Galbraith et open source community <patg at patg dot net> (4.022)
* Fixes for Win32 from Rom Hoelz (https://github.com/hoelzro)
* Pulling back in work for 4.021 that didn't get pushed and much other work from Chip Salzenberg (https://github.com/chipdude)
* Column info order fix from Tokuhiro Matsuno (https://github.com/tokuhirom)
* Fix AutoCommit comparison logic to avoid spurious commands to mysql from Matthew Horsfall (https://github.com/wolfsage)
* server_preapre can't bind placeholder on comment. from Misahiro Chiba (https://github.com/nihen)
* server_prepare; data is null, allocate big memory bug. from Misahiro Chiba (https://github.com/nihen)
t/42bindparam.t
t/43count_params.t
t/44call_placeholder.t
t/44limit_placeholder.t
t/45bind_no_backslash_escapes.t
t/50chopblanks.t
t/50commit.t
t/51bind_type_guessing.t
t/52comment.t
t/53comment.t
t/55unicode.t
t/55utf8.t
t/55utf8mb4.t
t/55utf8_jp.t
t/56connattr.t
t/60leaks.t
t/65segfault.t
t/65types.t
t/70takeimp.t
t/71impdata.t
t/75supported_sql.t
If MySQL's "utf8mb4" is not supported by server, fallback to MySQL's "utf8".
If MySQL's "utf8mb4" is not supported by client, connect with "utf8" and issue SET NAMES 'utf8mb4'.
MYSQL_SET_CHARSET_NAME option (prior to establishing connection) sets client's charset.
Some clients think that they were connected with MYSQL_SET_CHARSET_NAME, but reality can be different.
This problem was reported in MariaDB bug tracker https://jira.mariadb.org/browse/CONC-342
but problem is not going to be fixed. So always manually issue SET NAMES to prevent misbehave.
To enable UTF-8 storage on server it is needed to configure it via session variable character_set_server.
Some clients provides function get_charset_number() to check if charset is supported.
If MySQL client does not support specified charset it used to print error message to stdout or stderr.
DBD::MariaDB expects that whole communication with server is encoded in UTF-8.
By default broken utf8mb4_general_ci collation is used. So change it to utf8mb4_unicode_ci which is according to the Unicode 4.0.0.
*/
#ifdef HAVE_GET_CHARSET_NUMBER
client_supports_utf8mb4 = get_charset_number("utf8mb4", MY_CS_PRIMARY) ? TRUE : FALSE;
#elif MYSQL_VERSION_ID < 50503
client_supports_utf8mb4 = FALSE;
#else
client_supports_utf8mb4 = TRUE;
#endif
connected = FALSE;
if (client_supports_utf8mb4)
mysql_query(sock, "SET character_set_server = 'utf8mb4'") != 0)
{
if (mysql_errno(sock) != ER_UNKNOWN_CHARACTER_SET)
{
mariadb_dr_do_error(dbh, mysql_errno(sock), mysql_error(sock), mysql_sqlstate(sock));
mariadb_db_disconnect(dbh, imp_dbh);
return FALSE;
}
if (mysql_query(sock, "SET NAMES 'utf8'") != 0 ||
mysql_query(sock, "SET character_set_server = 'utf8'") != 0 ||
mysql_query(sock, "SET collation_connection = 'utf8_unicode_ci'") != 0 ||
mysql_query(sock, "SET collation_server = 'utf8_unicode_ci'") != 0)
{
mariadb_dr_do_error(dbh, mysql_errno(sock), mysql_error(sock), mysql_sqlstate(sock));
mariadb_db_disconnect(dbh, imp_dbh);
return FALSE;
}
}
else
{
if (mysql_query(sock, "SET collation_connection = 'utf8mb4_unicode_ci'") != 0 ||
mysql_query(sock, "SET collation_server = 'utf8mb4_unicode_ci'") != 0)
{
mariadb_dr_do_error(dbh, mysql_errno(sock), mysql_error(sock), mysql_sqlstate(sock));
mariadb_db_disconnect(dbh, imp_dbh);
return FALSE;
}
}
/*
we turn off Mysql's auto reconnect and handle re-connecting ourselves
so that we can keep track of when this happens.
t/05dbcreate.t view on Meta::CPAN
my $failed = not eval { $dbh->do("ALTER DATABASE " . $dbh->quote_identifier($test_db) . " CHARACTER SET '$newcharset'") };
fatal_error "No permission to change charset for '$test_db' database on '$test_dsn' for user '$test_user'" if $failed;
diag "Changed charset for '$test_db' database to '$newcharset'";
$charset = $newcharset;
}
}
my $collation = $dbh->selectrow_array('SELECT @@collation_database');
diag "Database '$test_db' has collation '$collation'";
if ($collation ne "${charset}_unicode_ci") {
my $newcollation = "${charset}_unicode_ci";
my $failed = not eval { $dbh->do("ALTER DATABASE " . $dbh->quote_identifier($test_db) . " COLLATE '$newcollation'") };
fatal_error "No permission to change collation for '$test_db' database on '$test_dsn' for user '$test_user'" if $failed;
diag "Changed collation for '$test_db' database to '$newcollation'";
$collation = $newcollation;
}
$dbh->disconnect();
plan tests => 1;
pass "Database '$test_db' is ready for DBD::MariaDB tests";
binutf VARCHAR(64) CHARACTER SET utf8 COLLATE utf8_bin,
profile TEXT CHARACTER SET utf8,
str2 VARCHAR(64) CHARACTER SET utf8,
ascii VARCHAR(64) CHARACTER SET latin1,
latin VARCHAR(64) CHARACTER SET latin1
)
EOT
ok $dbh->do($create);
my $unicode_str = "\N{U+0100}dam"; # Unicode "Adam" with a macron (internally stored as utf8)
my $quoted_unicode_str = "'\N{U+0100}dam'";
my $blob = "\x{c4}\x{80}dam"; # UTF-8 representation of $unicode_str
my $quoted_blob = "'\x{c4}\x{80}dam'";
my $unicode_str2 = "\x{c1}dam"; # Unicode "Adam" with a acute (internally stored as latin1)
my $ascii_str = "?dam"; # ASCII representation of $unicode_str (and also $unicode_str2)
my $latin1_str2 = "\x{c1}dam"; # Latin1 representation of $unicode_str2 (well, really same as $unicode_str2)
my $blob2 = "\x{c3}\x{81}dam"; # UTF-8 representation of $unicode_str2
cmp_ok $dbh->quote($unicode_str), 'eq', $quoted_unicode_str, 'testing quoting of utf 8 string';
cmp_ok $dbh->quote($blob), 'eq', $quoted_blob, 'testing quoting of blob';
ok $dbh->do("SET SQL_MODE=''"), 'SET SQL_MODE=\'\'';
# GeomFromText() is deprecated as of MySQL 5.7.6, use ST_GeomFromText() instead
my $geomfromtext = $dbh->{mariadb_serverversion} >= 50706 ? 'ST_GeomFromText' : 'GeomFromText';
my $query = <<EOI;
INSERT INTO dbd_mysql_t55utf8 (name, bincol, shape, binutf, profile, str2, ascii, latin)
VALUES (?, ?, $geomfromtext('Point(132865 501937)'), ?, ?, ?, ?, ?)
EOI
# Do not use prepared statements because ST_GeomFromText() is not supported
# With SET SQL_MODE='' is mariadb_server_prepare_disable_fallback not working
# And without SET SQL_MODE='' below 'Incorrect string value' are fatal errors, not warnings...
my $sth = $dbh->prepare($query, { mariadb_server_prepare => 0 });
ok $sth->bind_param(1, $unicode_str);
ok $sth->bind_param(2, $blob, DBI::SQL_BINARY);
ok $sth->bind_param(3, $unicode_str);
ok $sth->bind_param(4, $unicode_str);
ok $sth->bind_param(5, $unicode_str2);
ok $sth->bind_param(6, $unicode_str);
ok $sth->bind_param(7, $unicode_str2);
ok $sth->execute();
cmp_ok($dbh->{mariadb_warning_count}, '==', 1, 'got warning for INSERT') or do { diag("SHOW WARNINGS:"); diag($_->[2]) foreach $dbh->selectall_array("SHOW WARNINGS", { mariadb_server_prepare => 0 }); };
my (undef, undef, $warning) = $dbh->selectrow_array("SHOW WARNINGS", { mariadb_server_prepare => 0 });
like($warning, qr/^(?:Incorrect string value: '\\xC4\\x80dam'|Data truncated) for column (?:'ascii'|`.*`\.`.*`\.`ascii`) at row 1$/, 'warning is correct');
# AsBinary() is deprecated as of MySQL 5.7.6, use ST_AsBinary() instead
my $asbinary = $dbh->{mariadb_serverversion} >= 50706 ? 'ST_AsBinary' : 'AsBinary';
$query = "SELECT name,bincol,$asbinary(shape), binutf, profile, str2, ascii, latin FROM dbd_mysql_t55utf8 LIMIT 1";
$sth = $dbh->prepare($query);
ok $sth->execute;
my $ref;
$ref = $sth->fetchrow_arrayref ;
ok defined $ref, 'got data' or $ref = [];
cmp_ok $ref->[0], 'eq', $unicode_str;
cmp_ok $ref->[1], 'eq', $blob;
cmp_ok $ref->[3], 'eq', $unicode_str;
cmp_ok $ref->[4], 'eq', $unicode_str;
cmp_ok $ref->[5], 'eq', $unicode_str2;
cmp_ok $ref->[6], 'eq', $ascii_str;
cmp_ok $ref->[7], 'eq', $latin1_str2;
cmp_ok $ref->[1], 'eq', $blob, "compare $ref->[1] eq $blob";
my $prev_charset = $dbh->selectrow_array('SELECT @@character_set_results');
ok $dbh->do("SET character_set_results='latin1'"), "SET character_set_results='latin1'";
$ref = $dbh->selectrow_arrayref($query);
ok defined $ref, 'got data' or $ref = [];
cmp_ok $ref->[0], 'eq', $ascii_str, 'utf8 data are returned as latin1 when @@character_set_results is latin1';
cmp_ok $ref->[1], 'eq', $blob, 'blob is unchanged when @@character_set_results is latin1';
cmp_ok $ref->[3], 'eq', $ascii_str, 'utf8 data are returned as latin1 when @@character_set_results is latin1';
cmp_ok $ref->[4], 'eq', $ascii_str, 'utf8 data are returned as latin1 when @@character_set_results is latin1';
cmp_ok $ref->[5], 'eq', $latin1_str2, 'utf8 data are returned as latin1 when @@character_set_results is latin1';
cmp_ok $ref->[6], 'eq', $ascii_str, 'latin1 data are returned as latin1 when @@character_set_results is latin1';
cmp_ok $ref->[7], 'eq', $latin1_str2, 'latin1 data are returned as latin1 when @@character_set_results is latin1';
ok $sth = $dbh->prepare("SELECT 1 FROM dbd_mysql_t55utf8 WHERE bincol = ?");
ok !defined eval { $sth->bind_param(1, $unicode_str, DBI::SQL_BINARY) };
like $@, qr/^Wide character in /, '';
ok $dbh->do("SET character_set_results='$prev_charset'"), "SET character_set_results='$prev_charset'";
ok $dbh->do("DROP TABLE dbd_mysql_t55utf8");
ok $dbh->disconnect;
}
t/90utf8_params.t view on Meta::CPAN
use lib 't', '.';
require 'lib.pl';
my $tb = Test::More->builder;
binmode $tb->output, ":utf8";
binmode $tb->failure_output, ":utf8";
binmode $tb->todo_output, ":utf8";
my $dbh = DbiTestConnect($test_dsn, $test_user, $test_password, { RaiseError => 1, PrintError => 0 });
my $nasty_unicode1 = "\N{U+C3}\N{U+BF}"; # looks like character 0xff, if you accidentally utf8 decode
utf8::downgrade($nasty_unicode1);
my $nasty_unicode2 = $nasty_unicode1;
utf8::upgrade($nasty_unicode2);
is($nasty_unicode1, $nasty_unicode2, "Perl's internal form does not matter");
my $nasty_bytes1 = chr(0xc3).chr(0xbf); # looks like character 0xff, if you accidentally utf8 decode
utf8::downgrade($nasty_bytes1);
my $nasty_bytes2 = $nasty_bytes1;
utf8::upgrade($nasty_bytes2);
is($nasty_bytes1, $nasty_bytes2, "Perl's internal form does not matter");
is($nasty_unicode1, $nasty_bytes1, "Perl does not distinguish between bytes and Unicode string");
is($nasty_unicode2, $nasty_bytes2, "Perl does not distinguish between bytes and Unicode string");
foreach my $server_prepare (0, 1) {
my $enable_str = "mariadb_server_prepare=$server_prepare";
my $enable_hash = { RaiseError => 1, PrintError => 0, mariadb_server_prepare => $server_prepare, mariadb_server_prepare_disable_fallback => 1 };
$dbh = DBI->connect($test_dsn, $test_user, $test_password, $enable_hash);
foreach my $charset ("latin1", "utf8") {
$dbh->do(qq{
CREATE TEMPORARY TABLE unicode_test (
payload VARCHAR(20),
id int(10)
) CHARACTER SET $charset
});
my $nasty_unicode1_param = $nasty_unicode1;
my $nasty_unicode2_param = $nasty_unicode2;
$dbh->do("INSERT INTO unicode_test (id, payload) VALUES (1, ?), (2, ?)", {}, $nasty_unicode1_param, $nasty_unicode2_param);
$dbh->do("INSERT INTO unicode_test (id, payload) VALUES (3, '$nasty_unicode1_param')");
$dbh->do("INSERT INTO unicode_test (id, payload) VALUES (4, '$nasty_unicode2_param')");
my $sth = $dbh->prepare("INSERT INTO unicode_test (id, payload) VALUES (?, ?)");
$sth->execute(5, $nasty_unicode1_param);
$sth->execute(6, $nasty_unicode2_param);
$sth = $dbh->prepare("INSERT INTO unicode_test (id, payload) VALUES (?, ?)");
$sth->bind_param(1, 7);
$sth->bind_param(2, $nasty_unicode1_param);
$sth->execute;
$sth = $dbh->prepare("INSERT INTO unicode_test (id, payload) VALUES (?, ?)");
$sth->bind_param(1, 8);
$sth->bind_param(2, $nasty_unicode2_param);
$sth->execute;
{
my $sql = "INSERT INTO unicode_test (id, payload) VALUES (?, ?)";
$sth = $dbh->prepare($sql);
}
$sth->execute(9, $nasty_unicode1_param);
$sth->execute(10, $nasty_unicode2_param);
{
my $sql = "INSERT INTO unicode_test (id, payload) VALUES (?, ?)";
$sth = $dbh->prepare($sql);
}
{
my $param = 1;
my $val = 11;
$sth->bind_param($param, $val);
}
{
my $param = 2;
my $val = $nasty_unicode1_param;
$sth->bind_param($param, $val);
}
$sth->execute;
{
my $sql = "INSERT INTO unicode_test (id, payload) VALUES (?, ?)";
$sth = $dbh->prepare($sql);
}
{
my $param = 1;
my $val = 12;
$sth->bind_param($param, $val);
}
{
my $param = 2;
my $val = $nasty_unicode2_param;
$sth->bind_param($param, $val);
}
$sth->execute;
my @trials = (
'do with supplied params',
'do with interpolated string',
'prepare then execute',
'prepare, bind, execute',
'prepare (free param) then execute',
'prepare (free param), bind (free param), execute',
);
for (my $i = 0; $i<@trials; $i++) {
my $id1 = $i*2+1;
my $id2 = $i*2+2;
(my $out) = $dbh->selectrow_array("SELECT payload FROM unicode_test WHERE id = $id1");
is($out, "\N{U+C3}\N{U+BF}", "unicode / $trials[$i] / utf8::downgrade / $charset / $enable_str");
($out) = $dbh->selectrow_array("SELECT payload FROM unicode_test WHERE id = $id2");
is($out, "\N{U+C3}\N{U+BF}", "unicode / $trials[$i] / utf8::upgrade / $charset / $enable_str");
}
$dbh->do("DROP TEMPORARY TABLE unicode_test");
$dbh->do(qq{
CREATE TEMPORARY TABLE blob_test (
payload BLOB,
id int(10)
) CHARACTER SET $charset
});
$::test_db = DBD::MariaDB->parse_dsn($driver_dsn)->{database};
$::test_db = 'test' unless $::test_db;
}
sub DbiTestConnect {
my $err;
my $dbh = eval { DBI->connect(@_) };
if ( $dbh ) {
my ($current_charset, $current_collation) = $dbh->selectrow_array('SELECT @@character_set_database, @@collation_database');
my $expected_charset = $dbh->selectrow_array("SHOW CHARSET LIKE 'utf8mb4'") ? 'utf8mb4' : 'utf8';
my $expected_collation = "${expected_charset}_unicode_ci";
if ($current_charset ne $expected_charset) {
$err = "Database charset is not $expected_charset, but $current_charset";
} elsif ($current_collation ne $expected_collation) {
$err = "Database collation is not $expected_collation, but $current_collation";
}
} else {
if ( $@ ) {
$err = $@;
$err =~ s/ at \S+ line \d+\.?\s*$//;
}
( run in 1.434 second using v1.01-cache-2.11-cpan-f29a10751f0 )