DBD-mysql
view release on metacpan or search on metacpan
* Add Dockerfile (#390)
* More cleanups of unneeded ifdefs (#385)
* Enable auto reconnect for ER_CLIENT_INTERACTION_TIMEOUT
* Try out issue template for GitHub
* 99compression.t: Only test on 8.x
* Only use MYSQL_OPT_COMPRESSION_ALGORITHMS on >=8.0.18
* Replace `mysql_ssl_set()` with `mysql_options()`
2023-10-24 Daniël van Eeden, DBI/DBD community (5.002)
* Add support for compression algorighm selection (#372)
* Correct handling of mysql_enable_utf8mb4 (#363)
* tests: Remove have_transactions usage from 50commit.t
* Makefile: Clearly report that MySQL 8.x is needed and do some cleanup
* add DBD::mysql::client_version() to have the client version without DB connections
* Update version test for v5.x
2023-10-04 Daniël van Eeden, DBI/DBD community (5.001)
* Only support MySQL 8.x as MySQL 5.7 is going EOL soon
* Remove use of MYSQL_OPT_RECONNECT
* Remove option to disable SSL/TLS at compile time
* Only support MySQL 5.7 GA client libraries
Libraries in mysql_config --libs output can be specified by library name
with the -l prefix or by absolute path to library name without any prefix.
Parameters must start with a hyphen, so treat all options without leading
hyphen in mysql_config --libs output as libraries with full path.
Partially fixes bug https://rt.cpan.org/Public/Bug/Display.html?id=100898
Fix by Pali Rohár.
* Fix support for magic scalars (pali)
(https://github.com/perl5-dbi/DBD-mysql/pull/76)
2016-12-12 Patrick Galbraith, Michiel Beijen, DBI/DBD community (4.041_1)
* Unicode fixes: when using mysql_enable_utf8 or mysql_enable_utf8mb4,
previous versions of DBD::mysql did not properly encode input statements
to UTF-8 and retrieved columns were always UTF-8 decoded regardless of the
column charset.
Fix by Pali Rohár.
Reported and feedback on fix by Marc Lehmann
(https://rt.cpan.org/Public/Bug/Display.html?id=87428)
Also, the UTF-8 flag was not set for decoded data:
(https://rt.cpan.org/Public/Bug/Display.html?id=53130)
* Return INTs with ZEROFILL as strings. Reported by Knarf, fix by Pali Rohár.
(https://rt.cpan.org/Public/Bug/Display.html?id=118977)
2007-3-22 Patrick Galbraith <patg at patg dot net> Jim Winstead <jimw@mysql.com> (4.004)
* Work around a bug in old 3.23 servers by specifying NOT NULL for fields used
as a primary key in tests. (Bug #20325, reported by Julian Ladisch)
* Add support for mysql_warning_count statement handle attribute. (Bug #25457,
patch from Philip Stoev)
* Add support for mysql_multi_statements connection option. (RT #12322, based
on patch from Doug Morris)
* Had to bump to 4.003 do to print statement in mysql.pm that made it
into the dist. Even though you can delete a file on CPAN, you cannot
re-upload it if it's the same name. Mea Culpa.
* UTF8-Flag not set with flag mysql_enable_utf8 and column collation utf8_bin patch,
Joost Diepenmaat, (RT #24738)
* Fixed do_error definition (Scott Hildreth, Tim Bunce)
* Conversion of test suite to Test::More
2007-3-5 Patrick Galbraith <patg at patg dot net> Jim Winstead <jimw@mysql.com> (4.003)
* Fix inclusion of non-primary keys in primary_key_info. (Bug #26786,
reported and patch by Dave Rolsky)
2007-3-1 Patrick Galbraith <patg at patg dot net> Jim Winstead <jimw@mysql.com> (4.002)
* Fix re-exec of Makefile.PL when forcing $ENV{LANG} to 'C'. (RT #25233,
"imp_dbh->use_server_side_prepare: %d\n",
imp_dbh->use_server_side_prepare);
if ((svp = hv_fetch(hv, "mysql_server_prepare_disable_fallback", 37, FALSE)) && *svp)
imp_dbh->disable_fallback_for_server_prepare = SvTRUE(*svp);
if (DBIc_TRACE_LEVEL(imp_xxh) >= 2)
PerlIO_printf(DBIc_LOGPIO(imp_xxh),
"imp_dbh->disable_fallback_for_server_prepare: %d\n",
imp_dbh->disable_fallback_for_server_prepare);
if ((svp = hv_fetch(hv, "mysql_enable_utf8mb4", 20, FALSE)) && *svp && SvTRUE(*svp)) {
mysql_options(sock, MYSQL_SET_CHARSET_NAME, "utf8mb4");
imp_dbh->enable_utf8mb4 = TRUE;
}
else if ((svp = hv_fetch(hv, "mysql_enable_utf8", 17, FALSE)) && *svp) {
/* Do not touch imp_dbh->enable_utf8 as we are called earlier
* than it is set and mysql_options() must be before:
* mysql_real_connect()
*/
mysql_options(sock, MYSQL_SET_CHARSET_NAME,
(SvTRUE(*svp) ? "utf8" : "latin1"));
if (DBIc_TRACE_LEVEL(imp_xxh) >= 2)
PerlIO_printf(DBIc_LOGPIO(imp_xxh),
"mysql_options: MYSQL_SET_CHARSET_NAME=%s\n",
(SvTRUE(*svp) ? "utf8" : "latin1"));
password ? password : "NULL");
imp_dbh->stats.auto_reconnects_ok= 0;
imp_dbh->stats.auto_reconnects_failed= 0;
imp_dbh->bind_type_guessing= FALSE;
imp_dbh->bind_comment_placeholders= FALSE;
imp_dbh->has_transactions= TRUE;
/* Safer we flip this to TRUE perl side if we detect a mod_perl env. */
imp_dbh->auto_reconnect = FALSE;
imp_dbh->enable_utf8 = FALSE; /* initialize mysql_enable_utf8 */
imp_dbh->enable_utf8mb4 = FALSE; /* initialize mysql_enable_utf8mb4 */
if (!my_login(aTHX_ dbh, imp_dbh))
{
if(imp_dbh->pmysql) {
do_error(dbh, mysql_errno(imp_dbh->pmysql),
mysql_error(imp_dbh->pmysql) ,mysql_sqlstate(imp_dbh->pmysql));
Safefree(imp_dbh->pmysql);
}
return FALSE;
else if (kl == 20 && strEQ(key, "mysql_server_prepare"))
imp_dbh->use_server_side_prepare = bool_value;
else if (kl == 37 && strEQ(key, "mysql_server_prepare_disable_fallback"))
imp_dbh->disable_fallback_for_server_prepare = bool_value;
else if (kl == 23 && strEQ(key,"mysql_no_autocommit_cmd"))
imp_dbh->no_autocommit_cmd = bool_value;
else if (kl == 24 && strEQ(key,"mysql_bind_type_guessing"))
imp_dbh->bind_type_guessing = bool_value;
else if (kl == 31 && strEQ(key,"mysql_bind_comment_placeholders"))
imp_dbh->bind_type_guessing = bool_value;
else if (kl == 17 && strEQ(key, "mysql_enable_utf8"))
imp_dbh->enable_utf8 = bool_value;
else if (kl == 20 && strEQ(key, "mysql_enable_utf8mb4"))
imp_dbh->enable_utf8mb4 = bool_value;
else
return FALSE; /* Unknown key */
if (cacheit) /* cache value for later DBI 'quick' fetch? */
(void)hv_store((HV*)SvRV(dbh), key, kl, cachesv, 0);
return TRUE;
}
/***************************************************************************
lib/DBD/mysql.pm view on Meta::CPAN
You can also set it after creation of the database handle:
$dbh->{mysql_use_result} = 0; # disable
$dbh->{mysql_use_result} = 1; # enable
You can also set or unset the C<mysql_use_result> setting on your statement
handle, when creating the statement handle or after it has been created.
See L</"STATEMENT HANDLES">.
=item mysql_enable_utf8
This attribute determines whether DBD::mysql should assume strings
stored in the database are utf8. This feature defaults to off.
When set, a data retrieved from a textual column type (char, varchar,
etc) will have the UTF-8 flag turned on if necessary. This enables
character semantics on that string. You will also need to ensure that
your database / table / column is configured to use UTF8. See for more
information the chapter on character set support in the MySQL manual:
L<http://dev.mysql.com/doc/refman/8.0/en/charset.html>
lib/DBD/mysql.pm view on Meta::CPAN
as text data by calling the C<utf8::downgrade()> function (it dies on wide
Unicode strings with codepoints above U+FF). See the following example:
# check that last name contains LATIN CAPITAL LETTER O WITH STROKE (U+D8)
my $statement = "SELECT * FROM users WHERE last_name LIKE '%\x{D8}%' AND first_name = ? AND data = ?";
my $wide_string_param = "Andr\x{E9}"; # Andre with LATIN SMALL LETTER E WITH ACUTE (U+E9)
my $byte_param = "\x{D8}\x{A0}\x{39}\x{F8}"; # some bytes (binary data)
my $dbh = DBI->connect('DBI:mysql:database', 'username', 'pass', { mysql_enable_utf8mb4 => 1 });
utf8::upgrade($statement); # UTF-8 fix for DBD::mysql
my $sth = $dbh->prepare($statement);
utf8::upgrade($wide_string_param); # UTF-8 fix for DBD::mysql
$sth->bind_param(1, $wide_string_param);
utf8::downgrade($byte_param); # byte fix for DBD::mysql
$sth->bind_param(2, $byte_param, DBI::SQL_BINARY); # set correct binary type
$sth->execute();
my $output = $sth->fetchall_arrayref();
# returned data in $output reference should be already UTF-8 decoded as appropriate
=item mysql_enable_utf8mb4
This is similar to mysql_enable_utf8, but is capable of handling 4-byte
UTF-8 characters.
=item mysql_bind_type_guessing
This attribute causes the driver (emulated prepare statements)
to attempt to guess if a value being bound is a numeric value,
and if so, doesn't quote the value. This was created by
Dragonchild and is one way to deal with the performance issue
of using quotes in a statement that is inserting or updating a
large numeric value. This was previously called
my $utf8_str = "\x{0100}dam"; # "Adam" with a macron.
my $quoted_utf8_str = "'\x{0100}dam'";
my $blob = "\x{c4}\x{80}dam"; # same as utf8_str but not utf8 encoded
my $quoted_blob = "'\x{c4}\x{80}dam'";
cmp_ok $dbh->quote($utf8_str), 'eq', $quoted_utf8_str, 'testing quoting of utf 8 string';
cmp_ok $dbh->quote($blob), 'eq', $quoted_blob, 'testing quoting of blob';
#ok $dbh->{mysql_enable_utf8}, "mysql_enable_utf8 survive connect()";
$dbh->{mysql_enable_utf8}=1;
# GeomFromText() is deprecated as of MySQL 5.7.6, use ST_GeomFromText() instead
my $geomfromtext = $dbh->{mysql_serverversion} >= 50706 ? 'ST_GeomFromText' : 'GeomFromText';
my $query = <<EOI;
INSERT INTO dbd_mysql_t55utf8 (name, bincol, shape, binutf, profile)
VALUES (?, ?, $geomfromtext('Point(132865 501937)'), ?, ?)
EOI
ok $dbh->do($query, {}, $utf8_str, $blob, $utf8_str, $utf8_str), "INSERT query $query\n";
t/55utf8_errors.t view on Meta::CPAN
if ($@) {
plan skip_all => "no database connection";
}
$dbh->disconnect();
plan tests => 10 * 3;
# All in internal Perl Unicode
my $jpnErr = qr/\x{4ed8}\x{8fd1}.*\x{884c}\x{76ee}/; # Use \x{...} instead \N{U+...} due to Perl 5.12.0 bug
foreach my $mysql_enable_utf8 (0, 1, 2) {
my %utf8_params = ();
if ($mysql_enable_utf8 == 1) {
$utf8_params{'mysql_enable_utf8'} = 1;
diag "Enabled mysql_enable_utf8.";
# XXX There are no utf8mb4 error characters
} elsif ($mysql_enable_utf8 == 2) {
$utf8_params{'mysql_enable_utf8mb4'} = 1;
diag "Enabled mysql_enable_utf8mb4.";
} else {
diag "Disabled mysql_enable_utf8.";
}
$dbh = DBI->connect($test_dsn, $test_user, $test_password,
{ RaiseError => 1, PrintError => 1, AutoCommit => 1, %utf8_params });
eval {
$dbh->do("SET lc_messages = 'ja_JP'");
} or do {
$dbh->disconnect();
plan skip_all => "Server lc_messages ja_JP are needed for this test";
};
t/55utf8_identifiers.t view on Meta::CPAN
use Test::More;
use DBI;
use Encode;
use vars qw($test_dsn $test_user $test_password);
use lib 't', '.';
require "lib.pl";
sub for_db {
my ($mysql_enable_utf8, $value) = @_; # Value is in internal Perl Unicode.
my $ret;
if ($mysql_enable_utf8 >= 1) {
$ret = $value;
} else {
$ret = Encode::encode('UTF-8', $value);
}
return $ret;
}
my $dbh;
eval {
t/55utf8_identifiers.t view on Meta::CPAN
# All in internal Perl Unicode
my $jpnTable = "\N{U+8868}"; # Japanese table
my $jpnColumn = "\N{U+6027}\N{U+5225}"; # Japanese column - word "gender"
my $jpnData1 = "\N{U+5c71}\N{U+7530}\N{U+592a}\N{U+90ce}"; # Japanese data - person name
my $jpnData2 = "\N{U+7537}"; # Japanese daya - word "male"
my $chiTable = "\N{U+5927}\N{U+99AC}"; # Chinese table XXX MySQL doesn't support utf8mb4 in table names
my $chiColumn = "\N{U+5C0F}\N{U+96EA}\N{U+4EBA}"; # Chinese column XXX MySQL doesn't support utf8mb4 in column names
my $chiData1 = "\N{U+30001}"; # Chinese data
my $chiData2 = "\N{U+30002}"; # Chinese data
foreach my $mysql_enable_utf8 (0, 1, 2) {
my %utf8_params = ();
if ($mysql_enable_utf8 == 1) {
$utf8_params{'mysql_enable_utf8'} = 1;
diag "Enabled mysql_enable_utf8.";
} elsif ($mysql_enable_utf8 == 2) {
$utf8_params{'mysql_enable_utf8mb4'} = 1;
diag "Enabled mysql_enable_utf8mb4.";
} else {
diag "Disabled mysql_enable_utf8.";
}
$dbh = DBI->connect($test_dsn, $test_user, $test_password,
{ RaiseError => 1, PrintError => 1, AutoCommit => 1, %utf8_params });
my $jpnTable_db = for_db($mysql_enable_utf8, $jpnTable);
my $jpnColumn_db = for_db($mysql_enable_utf8, $jpnColumn);
my $jpnData1_db = for_db($mysql_enable_utf8, $jpnData1);
my $jpnData2_db = for_db($mysql_enable_utf8, $jpnData2);
my ($chiTable_db, $chiColumn_db, $chiData1_db, $chiData2_db);
if ($mysql_enable_utf8 == 0 || $mysql_enable_utf8 == 2) {
$chiTable_db = for_db($mysql_enable_utf8, $chiTable);
$chiColumn_db = for_db($mysql_enable_utf8, $chiColumn);
$chiData1_db = for_db($mysql_enable_utf8, $chiData1);
$chiData2_db = for_db($mysql_enable_utf8, $chiData2);
}
my $sth;
my $row;
ok($dbh->do("DROP TABLE IF EXISTS $jpnTable_db"), 'Drop table for Japanese testing.');
if ($mysql_enable_utf8 == 0 || $mysql_enable_utf8 == 2) {
ok($dbh->do("DROP TABLE IF EXISTS $chiTable_db"), 'Drop table for Chinese testings.');
}
ok($dbh->do(<<"END"
CREATE TABLE IF NOT EXISTS $jpnTable_db (
name VARCHAR(20),
$jpnColumn_db CHAR(1)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin
END
), 'Create temporay table with Japanese characters.');
if ($mysql_enable_utf8 == 0 || $mysql_enable_utf8 == 2) {
ok($dbh->do(<<"END"
CREATE TABLE IF NOT EXISTS $chiTable_db (
name VARCHAR(20),
$chiColumn_db CHAR(1)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin
END
), 'Create temporay table with Chinese characters.');
}
ok($sth = $dbh->prepare("INSERT INTO $jpnTable_db (name, $jpnColumn_db) VALUES (?, ?)"), 'Prepare insert statement with Japanese values.');
ok($sth->execute($jpnData1_db, $jpnData2_db), 'Execute insert statement with Japanese values.');
if ($mysql_enable_utf8 == 0 || $mysql_enable_utf8 == 2) {
ok($sth = $dbh->prepare("INSERT INTO $chiTable_db (name, $chiColumn_db) VALUES (?, ?)"), 'Prepare insert statement with Chinese values.');
ok($sth->execute($chiData1_db, $chiData2_db), 'Execute insert statement with Chinese values.');
}
ok($sth = $dbh->prepare("SELECT * FROM $jpnTable_db"), 'Prepare select statement with Japanese values.');
ok($sth->execute(), 'Execute select statement with Japanese values.');
ok($row = $sth->fetchrow_hashref(), 'Fetch hashref with Japanese values.');
is($row->{name}, $jpnData1_db, "Japanese value.");
ok(!exists $row->{$jpnColumn}, 'Not exists Japanese key in internal Perl Unicode.'); # XXX
is($row->{Encode::encode('UTF-8', $jpnColumn)}, $jpnData2_db, 'Exists Japanese key in octets and value.'); # XXX
is_deeply($sth->{NAME}, [ 'name', Encode::encode('UTF-8', $jpnColumn) ], 'Statement Japanese column name is in octets.'); # XXX
is_deeply($sth->{mysql_table}, [ Encode::encode('UTF-8', $jpnTable), Encode::encode('UTF-8', $jpnTable) ], 'Statement Japanese table name is in octets.'); # XXX
if ($mysql_enable_utf8 == 0 || $mysql_enable_utf8 == 2) {
ok($sth = $dbh->prepare("SELECT * FROM $chiTable_db"), 'Prepare select statement with Chinese values.');
ok($sth->execute(), 'Execute select statement with Chinese values.');
ok($row = $sth->fetchrow_hashref(), 'Fetch hashref with Chinese values.');
is($row->{name}, $chiData1_db, "Chinese value.");
ok(!exists $row->{$chiColumn}, 'Not exists Chinese key in internal Perl Unicode.'); # XXX
is($row->{Encode::encode('UTF-8', $chiColumn)}, $chiData2_db, 'Exists Chinese key in octets and value.'); # XXX
is_deeply($sth->{NAME}, [ 'name', Encode::encode('UTF-8', $chiColumn) ], 'Statement Chinese column name is in octets.'); # XXX
is_deeply($sth->{mysql_table}, [ Encode::encode('UTF-8', $chiTable), Encode::encode('UTF-8', $chiTable) ], 'Statement Chinese table name is in octets.'); # XXX
}
use Test::More;
use DBI;
use lib 't', '.';
require 'lib.pl';
# https://github.com/perl5-dbi/DBD-mysql/issues/360
my ($dbhA, $dbhB);
use vars qw($test_dsn $test_user $test_password);
my $dsnA = $test_dsn . ';mysql_enable_utf8mb4=1';
eval {$dbhA = DBI->connect($dsnA, $test_user, $test_password,
{ RaiseError => 1, AutoCommit => 1});};
if ($@) {
diag $@;
plan skip_all => "no database connection";
}
my $dsnB = $test_dsn;
$dsnB =~ s/DBI:mysql/DBI:mysql(mysql_enable_utf8mb4=1)/;
eval {$dbhB = DBI->connect($dsnB . ';mysql_enable_utf8mb4=1', $test_user, $test_password,
{ RaiseError => 1, AutoCommit => 1});};
plan tests => 2;
ok($dbhA->{mysql_enable_utf8mb4} == 1, 'mysql_enable_utf8mb4 == 1 with regular DSN');
ok($dbhB->{mysql_enable_utf8mb4} == 1, 'mysql_enable_utf8mb4 == 1 with driver DSN');
( run in 0.426 second using v1.01-cache-2.11-cpan-00829025b61 )