Skip to content

Commit

Permalink
Switch from DBD::mysql to DBD::MariaDB
Browse files Browse the repository at this point in the history
DBD::mysql 5 recently dropped support for building from MySQL client
libraries prior to v8. This creates challenges for people still using
earlier versions, as well as those using MariaDB.

DBD::MariaDB forked from DBD::mysql back in 2018, and maintains
compatibility with both MySQL and MariaDB. It remains compatible with
earlier versions of MySQL as well as the MariaDB client libraries. It
also includes bug fixes and more transparent support for Unicode
encoding.

So switch from DBD::mysql to DBD::MariaDB. It's largely a drop-in
replacement, with just a few additional changes:

*   Add `_dsn()` to the mysql engine, to replace URI::mysql's
    specification of `dbi:mysql` with `dbi:MariaDB`
*   Remove incompatible config parameters `mysql_enable_utf8` (no longer
    needed due to the aforementioned Unicode bug fixes),
    `mysql_auto_reconnect`, and `mysql_use_result`.
*   Read DBI handle attributes starting with `mariadb_` instead of
    `mysql_`.
*   Add a `USE` statement to set the registry as the current database
    after it has been created. Not sure how this wasn't required when
    using DBD::mysql, but aligns more closely with the requirements of
    other engines.

Resolves #825.
  • Loading branch information
theory committed Jan 3, 2025
1 parent 33291bd commit 2b6debb
Show file tree
Hide file tree
Showing 11 changed files with 51 additions and 44 deletions.
2 changes: 1 addition & 1 deletion .github/ubuntu/mysql.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@ set -e
if [ -z "$SKIP_DEPENDS" ]; then
sudo apt-get update -qq
sudo apt-get remove -qq mysql-common # https://github.com/actions/virtual-environments/issues/5067#issuecomment-1038752575
sudo env DEBIAN_FRONTEND=noninteractive apt-get install -qq mysql-client default-libmysqlclient-dev
sudo env DEBIAN_FRONTEND=noninteractive apt-get install -qq mariadb-client libmariadb3
fi
2 changes: 1 addition & 1 deletion .github/workflows/coverage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ jobs:
.github/ubuntu/snowflake.sh
.github/ubuntu/vertica.sh
- run: cpm install --verbose --show-build-log-on-failure --no-test --with-recommends --cpanfile dist/cpanfile
- run: cpm install --verbose --show-build-log-on-failure --no-test --with-recommends DBI DBD::ODBC DBD::Firebird DBD::Oracle DBD::mysql DBD::Pg Devel::Cover Devel::Cover::Report::Coveralls
- run: cpm install --verbose --show-build-log-on-failure --no-test --with-recommends DBI DBD::ODBC DBD::Firebird DBD::Oracle DBD::MariaDB DBD::Pg Devel::Cover Devel::Cover::Report::Coveralls
- name: Run Tests
env:
PERL5LIB: "${{ github.workspace }}/local/lib/perl5"
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/mysql.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ jobs:
runs-on: ubuntu-latest
services:
# Run the MySQL service in a container we can connect to. Means that the
# CLI and libraries DBD::mysql use are static to the version on the runner
# CLI and libraries DBD::MariaDB use are static to the version on the runner
# machine.
mysql:
image: "${{ matrix.image }}:${{ matrix.version }}"
Expand All @@ -63,7 +63,7 @@ jobs:
path: local
key: perl-${{ steps.perl.outputs.perl-hash }}
- run: cpm install --verbose --show-build-log-on-failure --no-test --with-recommends --cpanfile dist/cpanfile
- run: cpm install --verbose --show-build-log-on-failure --no-test --with-recommends DBD::mysql
- run: cpm install --verbose --show-build-log-on-failure --no-test --with-recommends DBD::MariaDB
- name: prove
env:
PERL5LIB: "${{ github.workspace }}/local/lib/perl5"
Expand Down
5 changes: 5 additions & 0 deletions Changes
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,11 @@ Revision history for Perl extension App::Sqitch
permission to create a schema and to skip the creation of the registry
schema. Useful for cases when the registry schema was created in
advance. Thanks to Peter Wimsey for the suggestion (#826).
- Switched the MySQL engine from DBD::mysql to DBD::MariaDB for better
compatibility with older versions of the MySQL client library and for
its Unicode improvements. Thanks to Mark Tyrrell for the report and
@tiberiusferreira and Perl Monks `1nickt` and`InfiniteSilence` for the
feedback (#825).

1.4.1 2024-02-04T16:35:32Z
- Removed the quoting of the role and warehouse identifiers that was
Expand Down
4 changes: 2 additions & 2 deletions dist.ini
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ Test::Spelling = 0
Test::MockObject::Extends = 1.20180705
DBD::SQLite = 1.37
DBD::Pg = 2.0
DBD::mysql = 4.018
DBD::MariaDB = 1.0
MySQL::Config = 0
DBD::Firebird = 1.11
DBD::ODBC = 1.59
Expand Down Expand Up @@ -107,7 +107,7 @@ DBD::SQLite = 1.37
[OptionalFeature / mysql]
-description = Support for managing MySQL databases
-prompt = 0
DBD::mysql = 4.018
DBD::MariaDB = 1.0
MySQL::Config = 0

[OptionalFeature / firebird]
Expand Down
6 changes: 3 additions & 3 deletions dist/cpanfile
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ suggests "DBD::ODBC" => "1.59";
suggests "DBD::Oracle" => "1.23";
suggests "DBD::Pg" => "2.0";
suggests "DBD::SQLite" => "1.37";
suggests "DBD::mysql" => "4.018";
suggests "DBD::MariaDB" => "1.0";
suggests "MySQL::Config" => "0";
suggests "Time::HiRes" => "0";
suggests "Time::Local" => "0";
Expand Down Expand Up @@ -120,7 +120,7 @@ on 'develop' => sub {
requires "DBD::Oracle" => "1.23";
requires "DBD::Pg" => "2.0";
requires "DBD::SQLite" => "1.37";
requires "DBD::mysql" => "4.018";
requires "DBD::MariaDB" => "1.0";
requires "MySQL::Config" => "0";
requires "Time::HiRes" => "0";
requires "Time::Local" => "0";
Expand All @@ -131,7 +131,7 @@ on 'develop' => sub {
recommends "DBD::ODBC" => "1.59";
recommends "DBD::Pg" => "2.0";
recommends "DBD::SQLite" => "1.37";
recommends "DBD::mysql" => "4.018";
recommends "DBD::MariaDB" => "1.0";
recommends "Dist::Zilla" => "5";
recommends "Dist::Zilla::Plugin::AutoPrereqs" => "0";
recommends "Dist::Zilla::Plugin::CPANFile" => "0";
Expand Down
2 changes: 1 addition & 1 deletion dist/sqitch.spec
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ Group: Development/Libraries
Requires: sqitch >= %{version}
Requires: mysql >= 5.1.0
Requires: perl(DBI) >= 1.631
Requires: perl(DBD::mysql) >= 4.018
Requires: perl(DBD::MariaDB) >= 1.0
Requires: perl(MySQL::Config)
Provides: sqitch-mysql

Expand Down
2 changes: 1 addition & 1 deletion inc/Menlo/Sqitch.pm
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ Runtime-only dependencies
DBD-ODBC
DBD-Oracle
DBD-Pg
DBD-mysql
DBD-MariaDB
Data-OptList
DateTime
DateTime-Locale
Expand Down
38 changes: 20 additions & 18 deletions lib/App/Sqitch/Engine/mysql.pm
Original file line number Diff line number Diff line change
Expand Up @@ -64,29 +64,30 @@ has _mycnf => (
sub _def_user { $_[0]->_mycnf->{user} || $_[0]->sqitch->sysuser }
sub _def_pass { $ENV{MYSQL_PWD} || shift->_mycnf->{password} }

sub _dsn {
(my $dsn = $_[1]->dbi_dsn) =~ s/\Adbi:mysql/dbi:MariaDB/;
return $dsn;
}

has dbh => (
is => 'rw',
isa => DBH,
lazy => 1,
default => sub {
my $self = shift;
$self->use_driver;
my $uri = $self->registry_uri;
my $dbh = DBI->connect($uri->dbi_dsn, $self->username, $self->password, {
PrintError => 0,
RaiseError => 0,
AutoCommit => 1,
mysql_enable_utf8 => 1,
mysql_auto_reconnect => 0,
mysql_use_result => 0, # Prevent "Commands out of sync" error.
HandleError => $self->error_handler,
Callbacks => {
my $dbh = DBI->connect($self->_dsn($self->uri), $self->username, $self->password, {
PrintError => 0,
RaiseError => 0,
AutoCommit => 1,
HandleError => $self->error_handler,
Callbacks => {
connected => sub {
my $dbh = shift;
$dbh->do("SET SESSION $_") or return for (
q{character_set_client = 'utf8'},
q{character_set_server = 'utf8'},
($dbh->{mysql_serverversion} || 0 < 50500 ? () : (q{default_storage_engine = 'InnoDB'})),
($dbh->{mariadb_serverversion} || 0 < 50500 ? () : (q{default_storage_engine = 'InnoDB'})),
q{time_zone = '+00:00'},
q{group_concat_max_len = 32768},
q{sql_mode = '} . join(',', qw(
Expand All @@ -105,15 +106,15 @@ has dbh => (
});

# Make sure we support this version.
my ($dbms, $vnum, $vstr) = $dbh->{mysql_serverinfo} =~ /mariadb/i
my ($dbms, $vnum, $vstr) = $dbh->{mariadb_serverinfo} =~ /mariadb/i
? ('MariaDB', 50300, '5.3')
: ('MySQL', 50100, '5.1.0');
hurl mysql => __x(
'Sqitch requires {rdbms} {want_version} or higher; this is {have_version}',
rdbms => $dbms,
want_version => $vstr,
have_version => $dbh->selectcol_arrayref('SELECT version()')->[0],
) unless $dbh->{mysql_serverversion} >= $vnum;
) unless $dbh->{mariadb_serverversion} >= $vnum;

return $dbh;
}
Expand Down Expand Up @@ -211,17 +212,17 @@ has _fractional_seconds => (
lazy => 1,
default => sub {
my $dbh = shift->dbh;
return $dbh->{mysql_serverinfo} =~ /mariadb/i
? $dbh->{mysql_serverversion} >= 50305
: $dbh->{mysql_serverversion} >= 50604;
return $dbh->{mariadb_serverinfo} =~ /mariadb/i
? $dbh->{mariadb_serverversion} >= 50305
: $dbh->{mariadb_serverversion} >= 50604;
},
);

sub mysql { @{ shift->_mysql } }

sub key { 'mysql' }
sub name { 'MySQL' }
sub driver { 'DBD::mysql 4.018' }
sub driver { 'DBD::MariaDB 1.0' }
sub default_client { 'mysql' }

sub _char2ts {
Expand Down Expand Up @@ -282,6 +283,7 @@ sub _initialize {
# Deploy the registry to the Sqitch database.
$self->run_upgrade( file(__FILE__)->dir->file('mysql.sql') );
$self->_set_initialized(1);
$self->dbh->do('USE ' . $self->dbh->quote_identifier($self->registry));
$self->_register_release;
}

Expand Down Expand Up @@ -478,7 +480,7 @@ sub _prepare_registry_file {

# Strip out 5.5 stuff on earlier versions.
$sql =~ s/-- ## BEGIN 5[.]5.+?-- ## END 5[.]5//ms
if $self->dbh->{mysql_serverversion} < 50500;
if $self->dbh->{mariadb_serverversion} < 50500;
}

if (!$can_create_checkit) {
Expand Down
2 changes: 1 addition & 1 deletion po/fr_FR.po
Original file line number Diff line number Diff line change
Expand Up @@ -1618,7 +1618,7 @@ msgstr "L'email utilisateur ne peut contenir \">\""
#~ msgstr "Cible de déploiement inconnue : \"{target}\""

#, fuzzy
#~ msgid "DBD::mysql module required to manage MySQL"
#~ msgid "DBD::MariaDB module required to manage MySQL"
#~ msgstr "Module DBD::Pg requis pour gérer PostgreSQL"

#, fuzzy
Expand Down
28 changes: 14 additions & 14 deletions t/mysql.t
Original file line number Diff line number Diff line change
Expand Up @@ -381,23 +381,23 @@ is $mysql->_limit_default, '18446744073709551615', 'Should have _limit_default';

SECS: {
my $mock = Test::MockModule->new($CLASS);
my $dbh = {mysql_serverinfo => 'foo', mysql_serverversion => 50604};
my $dbh = {mariadb_serverinfo => 'foo', mariadb_serverversion => 50604};
$mock->mock(dbh => $dbh);
is $mysql->_ts_default, 'utc_timestamp(6)',
'Should have _ts_default with fractional seconds';

$dbh->{mysql_serverversion} = 50101;
$dbh->{mariadb_serverversion} = 50101;
my $my51 = $CLASS->new(sqitch => $sqitch, target => $target);
is $my51->_ts_default, 'utc_timestamp',
'Should have _ts_default without fractional seconds on 5.1';

$dbh->{mysql_serverversion} = 50304;
$dbh->{mysql_serverinfo} = 'Something about MariaDB man';
$dbh->{mariadb_serverversion} = 50304;
$dbh->{mariadb_serverinfo} = 'Something about MariaDB man';
my $maria = $CLASS->new(sqitch => $sqitch, target => $target);
is $maria->_ts_default, 'utc_timestamp',
'Should have _ts_default without fractional seconds on early mariadb';

$dbh->{mysql_serverversion} = 50305;
$dbh->{mariadb_serverversion} = 50305;
is $mysql->_ts_default, 'utc_timestamp(6)',
'Should have _ts_default with fractional secondson mariadb 5.03.05';
}
Expand Down Expand Up @@ -516,7 +516,7 @@ UPGRADE: {
my $fracsec;
my $version = 50500;
$mock->mock(_fractional_seconds => sub { $fracsec });
$mock->mock(dbh => sub { { mysql_serverversion => $version } });
$mock->mock(dbh => sub { { mariadb_serverversion => $version } });
$mock->mock(_can_create_immutable_function => 1);

# Mock run.
Expand Down Expand Up @@ -596,26 +596,26 @@ END {
$uri = URI->new(
$ENV{SQITCH_TEST_MYSQL_URI} ||
$ENV{MYSQL_URI} ||
'db:mysql://root@/information_schema'
'db:mariadb://root@/information_schema'
);
$uri->dbname('information_schema') unless $uri->dbname;
my $err = try {
$mysql->use_driver;
$dbh = DBI->connect($uri->dbi_dsn, $uri->user, $uri->password, {
$dbh = DBI->connect($mysql->_dsn($uri), $uri->user, $uri->password, {
PrintError => 0,
RaiseError => 0,
AutoCommit => 1,
HandleError => $mysql->error_handler,
});

# Make sure we have a version we can use.
if ($dbh->{mysql_serverinfo} =~ /mariadb/i) {
die "MariaDB >= 50300 required; this is $dbh->{mysql_serverversion}\n"
unless $dbh->{mysql_serverversion} >= 50300;
if ($dbh->{mariadb_serverinfo} =~ /mariadb/i) {
die "MariaDB >= 50300 required; this is $dbh->{mariadb_serverversion}\n"
unless $dbh->{mariadb_serverversion} >= 50300;
}
else {
die "MySQL >= 50100 required; this is $dbh->{mysql_serverversion}\n"
unless $dbh->{mysql_serverversion} >= 50100;
die "MySQL >= 50100 required; this is $dbh->{mariadb_serverversion}\n"
unless $dbh->{mariadb_serverversion} >= 50100;
}

$dbh->do("CREATE DATABASE $db");
Expand Down Expand Up @@ -650,7 +650,7 @@ DBIEngineTest->run(
for my $spec (
[character_set_client => qr/^utf8/],
[character_set_server => qr/^utf8/],
($dbh->{mysql_serverversion} < 50500 ? () : ([default_storage_engine => qr/^InnoDB$/])),
($dbh->{mariadb_serverversion} < 50500 ? () : ([default_storage_engine => qr/^InnoDB$/])),
[time_zone => qr/^\+00:00$/],
[group_concat_max_len => qr/^32768$/],
) {
Expand Down

0 comments on commit 2b6debb

Please sign in to comment.