DBD-MariaDB

 view release on metacpan or  search on metacpan

Changes  view on Meta::CPAN

 - 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)

MANIFEST  view on Meta::CPAN

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

dbdimp.c  view on Meta::CPAN

      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)

dbdimp.c  view on Meta::CPAN

        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";

t/55utf8.t  view on Meta::CPAN

    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
        });

t/lib.pl  view on Meta::CPAN

    $::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 0.532 second using v1.01-cache-2.11-cpan-88abd93f124 )