Skip to content

Commit d17dff9

Browse files
committed
Switch from DBD::mysql to DBD::MariaDB
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 DBIEngine and always use it to connect to the database. Override it in mysql.pm to replace `dbi:mysql` with `dbi:MariaDB`. Also override it in some other drivers that mangle the value returned by URI::db. * 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.
1 parent 33291bd commit d17dff9

24 files changed

+94
-69
lines changed

.github/ubuntu/mysql.sh

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,5 @@ set -e
66
if [ -z "$SKIP_DEPENDS" ]; then
77
sudo apt-get update -qq
88
sudo apt-get remove -qq mysql-common # https://github.com/actions/virtual-environments/issues/5067#issuecomment-1038752575
9-
sudo env DEBIAN_FRONTEND=noninteractive apt-get install -qq mysql-client default-libmysqlclient-dev
9+
sudo env DEBIAN_FRONTEND=noninteractive apt-get install -qq mariadb-client libmariadbd-dev
1010
fi

.github/workflows/coverage.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ jobs:
7575
.github/ubuntu/snowflake.sh
7676
.github/ubuntu/vertica.sh
7777
- run: cpm install --verbose --show-build-log-on-failure --no-test --with-recommends --cpanfile dist/cpanfile
78-
- 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
78+
- 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
7979
- name: Run Tests
8080
env:
8181
PERL5LIB: "${{ github.workspace }}/local/lib/perl5"

.github/workflows/mysql.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ jobs:
4242
runs-on: ubuntu-latest
4343
services:
4444
# Run the MySQL service in a container we can connect to. Means that the
45-
# CLI and libraries DBD::mysql use are static to the version on the runner
45+
# CLI and libraries DBD::MariaDB use are static to the version on the runner
4646
# machine.
4747
mysql:
4848
image: "${{ matrix.image }}:${{ matrix.version }}"
@@ -63,7 +63,7 @@ jobs:
6363
path: local
6464
key: perl-${{ steps.perl.outputs.perl-hash }}
6565
- run: cpm install --verbose --show-build-log-on-failure --no-test --with-recommends --cpanfile dist/cpanfile
66-
- run: cpm install --verbose --show-build-log-on-failure --no-test --with-recommends DBD::mysql
66+
- run: cpm install --verbose --show-build-log-on-failure --no-test --with-recommends DBD::MariaDB
6767
- name: prove
6868
env:
6969
PERL5LIB: "${{ github.workspace }}/local/lib/perl5"

Changes

+5
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,11 @@ Revision history for Perl extension App::Sqitch
4444
permission to create a schema and to skip the creation of the registry
4545
schema. Useful for cases when the registry schema was created in
4646
advance. Thanks to Peter Wimsey for the suggestion (#826).
47+
- Switched the MySQL engine from DBD::mysql to DBD::MariaDB for better
48+
compatibility with older versions of the MySQL client library and for
49+
its Unicode improvements. Thanks to Mark Tyrrell for the report and
50+
@tiberiusferreira and Perl Monks `1nickt` and`InfiniteSilence` for the
51+
feedback (#825).
4752

4853
1.4.1 2024-02-04T16:35:32Z
4954
- Removed the quoting of the role and warehouse identifiers that was

dist.ini

+2-2
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ Test::Spelling = 0
7676
Test::MockObject::Extends = 1.20180705
7777
DBD::SQLite = 1.37
7878
DBD::Pg = 2.0
79-
DBD::mysql = 4.018
79+
DBD::MariaDB = 1.0
8080
MySQL::Config = 0
8181
DBD::Firebird = 1.11
8282
DBD::ODBC = 1.59
@@ -107,7 +107,7 @@ DBD::SQLite = 1.37
107107
[OptionalFeature / mysql]
108108
-description = Support for managing MySQL databases
109109
-prompt = 0
110-
DBD::mysql = 4.018
110+
DBD::MariaDB = 1.0
111111
MySQL::Config = 0
112112

113113
[OptionalFeature / firebird]

dist/cpanfile

+3-3
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ suggests "DBD::ODBC" => "1.59";
7171
suggests "DBD::Oracle" => "1.23";
7272
suggests "DBD::Pg" => "2.0";
7373
suggests "DBD::SQLite" => "1.37";
74-
suggests "DBD::mysql" => "4.018";
74+
suggests "DBD::MariaDB" => "1.0";
7575
suggests "MySQL::Config" => "0";
7676
suggests "Time::HiRes" => "0";
7777
suggests "Time::Local" => "0";
@@ -120,7 +120,7 @@ on 'develop' => sub {
120120
requires "DBD::Oracle" => "1.23";
121121
requires "DBD::Pg" => "2.0";
122122
requires "DBD::SQLite" => "1.37";
123-
requires "DBD::mysql" => "4.018";
123+
requires "DBD::MariaDB" => "1.0";
124124
requires "MySQL::Config" => "0";
125125
requires "Time::HiRes" => "0";
126126
requires "Time::Local" => "0";
@@ -131,7 +131,7 @@ on 'develop' => sub {
131131
recommends "DBD::ODBC" => "1.59";
132132
recommends "DBD::Pg" => "2.0";
133133
recommends "DBD::SQLite" => "1.37";
134-
recommends "DBD::mysql" => "4.018";
134+
recommends "DBD::MariaDB" => "1.0";
135135
recommends "Dist::Zilla" => "5";
136136
recommends "Dist::Zilla::Plugin::AutoPrereqs" => "0";
137137
recommends "Dist::Zilla::Plugin::CPANFile" => "0";

dist/sqitch.spec

+1-1
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,7 @@ Group: Development/Libraries
240240
Requires: sqitch >= %{version}
241241
Requires: mysql >= 5.1.0
242242
Requires: perl(DBI) >= 1.631
243-
Requires: perl(DBD::mysql) >= 4.018
243+
Requires: perl(DBD::MariaDB) >= 1.0
244244
Requires: perl(MySQL::Config)
245245
Provides: sqitch-mysql
246246

inc/Menlo/Sqitch.pm

+1-1
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ Runtime-only dependencies
219219
DBD-ODBC
220220
DBD-Oracle
221221
DBD-Pg
222-
DBD-mysql
222+
DBD-MariaDB
223223
Data-OptList
224224
DateTime
225225
DateTime-Locale

lib/App/Sqitch/Engine/exasol.pm

+1-2
Original file line numberDiff line numberDiff line change
@@ -124,8 +124,7 @@ has dbh => (
124124
my $self = shift;
125125
$self->use_driver;
126126

127-
my $uri = $self->uri;
128-
DBI->connect($uri->dbi_dsn, $self->username, $self->password, {
127+
DBI->connect($self->_dsn, $self->username, $self->password, {
129128
PrintError => 0,
130129
RaiseError => 0,
131130
AutoCommit => 1,

lib/App/Sqitch/Engine/firebird.pm

+5-3
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,10 @@ sub registry_destination {
6161

6262
sub _def_user { $ENV{ISC_USER} }
6363
sub _def_pass { $ENV{ISC_PASSWORD} }
64+
sub _dsn {
65+
my $uri = shift->registry_uri;
66+
return $uri->dbi_dsn . ';ib_dialect=3;ib_charset=UTF8';
67+
}
6468

6569
has dbh => (
6670
is => 'rw',
@@ -69,11 +73,9 @@ has dbh => (
6973
clearer => '_clear_dbh',
7074
default => sub {
7175
my $self = shift;
72-
my $uri = $self->registry_uri;
7376
$self->use_driver;
7477

75-
my $dsn = $uri->dbi_dsn . ';ib_dialect=3;ib_charset=UTF8';
76-
return DBI->connect($dsn, scalar $self->username, scalar $self->password, {
78+
return DBI->connect($self->_dsn, scalar $self->username, scalar $self->password, {
7779
PrintError => 0,
7880
RaiseError => 0,
7981
AutoCommit => 1,

lib/App/Sqitch/Engine/mysql.pm

+22-19
Original file line numberDiff line numberDiff line change
@@ -64,29 +64,30 @@ has _mycnf => (
6464
sub _def_user { $_[0]->_mycnf->{user} || $_[0]->sqitch->sysuser }
6565
sub _def_pass { $ENV{MYSQL_PWD} || shift->_mycnf->{password} }
6666

67+
sub _dsn {
68+
(my $dsn = shift->uri->dbi_dsn) =~ s/\Adbi:mysql/dbi:MariaDB/;
69+
return $dsn;
70+
}
71+
6772
has dbh => (
6873
is => 'rw',
6974
isa => DBH,
7075
lazy => 1,
7176
default => sub {
7277
my $self = shift;
7378
$self->use_driver;
74-
my $uri = $self->registry_uri;
75-
my $dbh = DBI->connect($uri->dbi_dsn, $self->username, $self->password, {
76-
PrintError => 0,
77-
RaiseError => 0,
78-
AutoCommit => 1,
79-
mysql_enable_utf8 => 1,
80-
mysql_auto_reconnect => 0,
81-
mysql_use_result => 0, # Prevent "Commands out of sync" error.
82-
HandleError => $self->error_handler,
83-
Callbacks => {
79+
my $dbh = DBI->connect($self->_dsn, $self->username, $self->password, {
80+
PrintError => 0,
81+
RaiseError => 0,
82+
AutoCommit => 1,
83+
HandleError => $self->error_handler,
84+
Callbacks => {
8485
connected => sub {
8586
my $dbh = shift;
8687
$dbh->do("SET SESSION $_") or return for (
8788
q{character_set_client = 'utf8'},
8889
q{character_set_server = 'utf8'},
89-
($dbh->{mysql_serverversion} || 0 < 50500 ? () : (q{default_storage_engine = 'InnoDB'})),
90+
($dbh->{mariadb_serverversion} || 0 < 50500 ? () : (q{default_storage_engine = 'InnoDB'})),
9091
q{time_zone = '+00:00'},
9192
q{group_concat_max_len = 32768},
9293
q{sql_mode = '} . join(',', qw(
@@ -105,15 +106,15 @@ has dbh => (
105106
});
106107

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

118119
return $dbh;
119120
}
@@ -211,17 +212,17 @@ has _fractional_seconds => (
211212
lazy => 1,
212213
default => sub {
213214
my $dbh = shift->dbh;
214-
return $dbh->{mysql_serverinfo} =~ /mariadb/i
215-
? $dbh->{mysql_serverversion} >= 50305
216-
: $dbh->{mysql_serverversion} >= 50604;
215+
return $dbh->{mariadb_serverinfo} =~ /mariadb/i
216+
? $dbh->{mariadb_serverversion} >= 50305
217+
: $dbh->{mariadb_serverversion} >= 50604;
217218
},
218219
);
219220

220221
sub mysql { @{ shift->_mysql } }
221222

222223
sub key { 'mysql' }
223224
sub name { 'MySQL' }
224-
sub driver { 'DBD::mysql 4.018' }
225+
sub driver { 'DBD::MariaDB 1.0' }
225226
sub default_client { 'mysql' }
226227

227228
sub _char2ts {
@@ -282,6 +283,7 @@ sub _initialize {
282283
# Deploy the registry to the Sqitch database.
283284
$self->run_upgrade( file(__FILE__)->dir->file('mysql.sql') );
284285
$self->_set_initialized(1);
286+
$self->dbh->do('USE ' . $self->dbh->quote_identifier($self->registry));
285287
$self->_register_release;
286288
}
287289

@@ -478,7 +480,7 @@ sub _prepare_registry_file {
478480

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

484486
if (!$can_create_checkit) {
@@ -501,11 +503,12 @@ sub _prepare_registry_file {
501503
# determine whether we have binary logging disabled, or trust function
502504
# creators, or have the SUPER privilege.
503505
sub _can_create_immutable_function {
506+
# Use md5() to prevent "Illegal mix of collations" errors.
504507
shift->dbh->selectcol_arrayref(q{
505508
SELECT @@log_bin = 0
506509
OR @@log_bin_trust_function_creators = 1
507510
OR (
508-
SELECT super_priv = 'Y' FROM mysql.user
511+
SELECT md5(super_priv) = md5('Y') FROM mysql.user
509512
WHERE CONCAT(user, '@', host) = current_user
510513
)
511514
})->[0]

lib/App/Sqitch/Engine/oracle.pm

+1-2
Original file line numberDiff line numberDiff line change
@@ -96,8 +96,7 @@ has dbh => (
9696
my $self = shift;
9797
$self->use_driver;
9898

99-
my $uri = $self->uri;
100-
DBI->connect($uri->dbi_dsn, $self->username, $self->password, {
99+
DBI->connect($self->_dsn, $self->username, $self->password, {
101100
PrintError => 0,
102101
RaiseError => 0,
103102
AutoCommit => 1,

lib/App/Sqitch/Engine/pg.pm

+1-2
Original file line numberDiff line numberDiff line change
@@ -112,9 +112,8 @@ has dbh => (
112112
my $self = shift;
113113
$self->use_driver;
114114

115-
my $uri = $self->uri;
116115
local $ENV{PGCLIENTENCODING} = 'UTF8';
117-
DBI->connect($uri->dbi_dsn, $self->username, $self->password, {
116+
DBI->connect($self->_dsn, $self->username, $self->password, {
118117
PrintError => 0,
119118
RaiseError => 0,
120119
AutoCommit => 1,

lib/App/Sqitch/Engine/snowflake.pm

+1-2
Original file line numberDiff line numberDiff line change
@@ -191,10 +191,9 @@ has dbh => (
191191
default => sub {
192192
my $self = shift;
193193
$self->use_driver;
194-
my $uri = $self->uri;
195194
my $wh = $self->warehouse;
196195
my $role = $self->role;
197-
DBI->connect($uri->dbi_dsn, $self->username, $self->password, {
196+
DBI->connect($self->_dsn, $self->username, $self->password, {
198197
PrintError => 0,
199198
RaiseError => 0,
200199
AutoCommit => 1,

lib/App/Sqitch/Engine/sqlite.pm

+2-2
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ sub key { 'sqlite' }
6161
sub name { 'SQLite' }
6262
sub driver { 'DBD::SQLite 1.37' }
6363
sub default_client { 'sqlite3' }
64+
sub _dsn { shift->registry_uri->dbi_dsn }
6465

6566
has dbh => (
6667
is => 'rw',
@@ -70,8 +71,7 @@ has dbh => (
7071
my $self = shift;
7172
$self->use_driver;
7273

73-
my $uri = $self->registry_uri;
74-
my $dbh = DBI->connect($uri->dbi_dsn, '', '', {
74+
my $dbh = DBI->connect($self->_dsn, '', '', {
7575
PrintError => 0,
7676
RaiseError => 0,
7777
AutoCommit => 1,

lib/App/Sqitch/Engine/vertica.pm

+12-9
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,17 @@ has _vsql => (
6868

6969
sub vsql { @{ shift->_vsql } }
7070

71+
sub _dsn {
72+
my $self = shift;
73+
# Set defaults in the URI.
74+
my $uri = $self->uri;
75+
# https://my.vertica.com/docs/5.1.6/HTML/index.htm#2736.htm
76+
$uri->dbname($ENV{VSQL_DATABASE}) if !$uri->dbname && $ENV{VSQL_DATABASE};
77+
$uri->host($ENV{VSQL_HOST}) if !$uri->host && $ENV{VSQL_HOST};
78+
$uri->port($ENV{VSQL_PORT}) if !$uri->_port && $ENV{VSQL_PORT};
79+
return $uri->dbi_dsn;
80+
}
81+
7182
has dbh => (
7283
is => 'rw',
7384
isa => DBH,
@@ -76,15 +87,7 @@ has dbh => (
7687
my $self = shift;
7788
$self->use_driver;
7889

79-
# Set defaults in the URI.
80-
my $target = $self->target;
81-
my $uri = $self->uri;
82-
# https://my.vertica.com/docs/5.1.6/HTML/index.htm#2736.htm
83-
$uri->dbname($ENV{VSQL_DATABASE}) if !$uri->dbname && $ENV{VSQL_DATABASE};
84-
$uri->host($ENV{VSQL_HOST}) if !$uri->host && $ENV{VSQL_HOST};
85-
$uri->port($ENV{VSQL_PORT}) if !$uri->_port && $ENV{VSQL_PORT};
86-
87-
DBI->connect($uri->dbi_dsn, $self->username, $self->password, {
90+
DBI->connect($self->_dsn, $self->username, $self->password, {
8891
PrintError => 0,
8992
RaiseError => 0,
9093
AutoCommit => 1,

lib/App/Sqitch/Role/DBIEngine.pm

+2
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ after use_driver => sub {
3939
DBI->trace(1) if $_[0]->sqitch->verbosity > 2;
4040
};
4141

42+
sub _dsn { shift->target->uri->dbi_dsn }
43+
4244
sub _dt($) {
4345
require App::Sqitch::DateTime;
4446
return App::Sqitch::DateTime->new(split /:/ => shift);

po/fr_FR.po

+1-1
Original file line numberDiff line numberDiff line change
@@ -1618,7 +1618,7 @@ msgstr "L'email utilisateur ne peut contenir \">\""
16181618
#~ msgstr "Cible de déploiement inconnue : \"{target}\""
16191619

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

16241624
#, fuzzy

t/dbiengine_role.t

+4-1
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ can_ok $CLASS, qw(
3232
_in_expr
3333
_register_release
3434
_version_query
35+
_dsn
3536
registry_version
3637
_cid
3738
earliest_change_id
@@ -72,10 +73,12 @@ can_ok $CLASS, qw(
7273
begin_work
7374
finish_work
7475
rollback_work
76+
_eh
77+
error_handler
7578
);
7679

7780
is App::Sqitch::Role::DBIEngine::_ts_default, 'DEFAULT',
78-
'_ts_default shoudld return DEFAULT';
81+
'_ts_default should return DEFAULT';
7982

8083
# Test various failure modes.
8184
my $role = bless {} => $CLASS;

t/firebird.t

+2
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ is $fb->name, 'Firebird', 'Name should be "Firebird"';
6565
is $fb->username, $ENV{ISC_USER}, 'Should have username from environment';
6666
is $fb->password, $ENV{ISC_PASSWORD}, 'Should have password from environment';
6767
is $fb->_limit_default, '18446744073709551615', 'Should have _limit_default';
68+
is $fb->_dsn, 'dbi:Firebird:dbname=sqitch.fdb;ib_dialect=3;ib_charset=UTF8',
69+
'Should append "ib_dialect=3;ib_charset=UTF8" to the DSN';
6870

6971
my $have_fb_client;
7072
if ($have_fb_driver && (my $client = try { $fb->client })) {

t/lib/DBIEngineTest.pm

+1-1
Original file line numberDiff line numberDiff line change
@@ -1773,7 +1773,7 @@ sub run {
17731773
ok $engine->wait_lock, 'Should not have to wait for lock';
17741774

17751775
# Make a second connection to the database.
1776-
my $dbh = DBI->connect($engine->uri->dbi_dsn, $engine->username, $engine->password, {
1776+
my $dbh = DBI->connect($engine->_dsn, $engine->username, $engine->password, {
17771777
PrintError => 0,
17781778
RaiseError => 0,
17791779
AutoCommit => 1,

0 commit comments

Comments
 (0)