File Coverage

blib/lib/DBIx/QuickDB/Driver/MariaDB.pm
Criterion Covered Total %
statement 42 81 51.8
branch 12 36 33.3
condition 5 27 18.5
subroutine 12 19 63.1
pod 2 9 22.2
total 73 172 42.4


line stmt bran cond sub pod time code
1             package DBIx::QuickDB::Driver::MariaDB;
2 8     8   289841 use strict;
  8         10  
  8         257  
3 8     8   30 use warnings;
  8         25  
  8         456  
4              
5             our $VERSION = '0.000052';
6              
7 8     8   1691 use IPC::Cmd qw/can_run/;
  8         151749  
  8         424  
8 8     8   1869 use Capture::Tiny qw/capture/;
  8         38090  
  8         360  
9              
10 8     8   46 use parent 'DBIx::QuickDB::Driver::MySQL';
  8         11  
  8         46  
11 8     8   449 use DBIx::QuickDB::Util::HashBase;
  8         14  
  8         40  
12              
13 13     13 0 29 sub provider { 'MariaDB' }
14              
15             sub verify_provider {
16 0     0 0 0 my $class = shift;
17 0         0 my ($bin, $provider) = @_;
18              
19 0   0     0 $provider //= $class->provider;
20              
21 0     0   0 my ($v, $stderr) = capture { system($bin, '-V') };
  0         0  
22 0 0       0 return 1 if $v =~ m/$provider/i;
23 0         0 return 0;
24             }
25              
26 8     8 0 37 sub server_bin_list { qw/mariadbd mysqld/ }
27 0     0 0 0 sub client_bin_list { qw/mariadb mysql/ }
28 0     0 0 0 sub install_bin_list { qw/mariadb-install-db mysql_install_db/ }
29              
30 13     13 0 63 sub dbd_driver_order { my $class = shift; $class->SUPER::dbd_driver_order($ENV{QDB_MARIADB_DBD}, $ENV{QDB_MYSQLD_DBD}) }
  13         68  
31              
32             sub list_env_vars {
33 0     0 1 0 my $self = shift;
34              
35 0         0 my @list = $self->SUPER::list_env_vars();
36              
37             return (
38             @list,
39 0         0 map { my $x = "$_"; $x =~ s/MYSQL/MARIADB/g; $x } @list,
  0         0  
  0         0  
  0         0  
40             );
41             }
42              
43             sub _default_config {
44 0     0   0 my $self = shift;
45              
46 0         0 my %config = $self->SUPER::_default_config(@_);
47              
48 0 0       0 if (defined($ENV{QDB_MARIADB_SSL_FIPS})) {
49 0         0 $config{mysqld}->{'ssl_fips_mode'} = "$ENV{QDB_MARIADB_SSL_FIPS}";
50             }
51              
52 0         0 $config{mysqld}->{'query_cache_limit'} = '1M';
53 0         0 $config{mysqld}->{'query_cache_size'} = '20M';
54              
55 0         0 $config{mariadbd} = $config{mysqld};
56 0         0 $config{mariadb} = $config{mysql};
57 0         0 $config{mariadb_safe} = $config{mysql_safe};
58              
59 0         0 return %config;
60             }
61              
62             # Releases where an information_schema 'table_constraints' or
63             # 'referential_constraints' scan that reaches information_schema's own tables
64             # locks a never-initialized ACL mutex under --skip-grant-tables and blocks
65             # forever: immune to KILL, and it prevents graceful server shutdown. QuickDB
66             # always starts the server with --skip-grant-tables, so these releases are not
67             # safe to use. Broken by upstream MDEV-38209, fixed by MDEV-38811.
68             my %BROKEN_IS_ACL_VERSIONS = (
69             '10.11.16' => 'fixed in 10.11.17',
70             '11.4.10' => 'fixed in 11.4.11',
71             '11.8.6' => 'fixed in 11.8.7',
72             '12.2.2' => 'never fixed, 12.2.2 is the final 12.2 release; use another series',
73             '12.3.1' => 'fixed in 12.3.2',
74             );
75              
76             sub broken_version_check {
77 10     10 0 170979 my $this = shift;
78 10         24 my ($bin) = @_;
79              
80 10 100       41 return undef if $ENV{QDB_MARIADB_IGNORE_BROKEN};
81 9 100 100     1634 return undef unless $bin && -x $bin;
82              
83 7     7   388 my ($out) = capture { system($bin, '-V') };
  7         43170  
84 7 100 66     6598 return undef unless $out && $out =~ m/\bVer\s+(\d+\.\d+\.\d+)-MariaDB\b/;
85              
86 6         38 my $version = $1;
87 6 100       103 my $fix = $BROKEN_IS_ACL_VERSIONS{$version} or return undef;
88              
89 4         166 return "MariaDB $version hangs unkillably on information_schema"
90             . " 'table_constraints' and 'referential_constraints' scans under"
91             . " --skip-grant-tables, which DBIx::QuickDB always uses (upstream bug"
92             . " MDEV-38811; $fix). Set QDB_MARIADB_IGNORE_BROKEN=1 to use this"
93             . " server anyway.";
94             }
95              
96             sub viable {
97 13     13 1 19 my $this = shift;
98 13         22 my ($spec) = @_;
99              
100 13 50       105 my %check = (ref($this) ? %$this : (), $this->_default_paths, %$spec);
101              
102 13         22 my @bad;
103              
104 13 50       50 push @bad => "Could not load either 'DBD::MariaDB' or 'DBD::mysql', needed for everything"
105             unless $this->dbd_driver;
106              
107 13 50       14 if (!keys %{$this->provider_info}) {
  13         45  
108 13         27 push @bad => "Installed MySQL is not " . $this->provider;
109             }
110             else {
111 0 0       0 if ($spec->{bootstrap}) {
    0          
112 0 0 0     0 push @bad => "'mysqld' and 'mariadbd' commands are missing, needed for bootstrap" unless $check{server} && -x $check{server};
113             }
114             elsif ($spec->{autostart}) {
115 0 0 0     0 push @bad => "'mysqld' and 'mariadbd' commands are missing, needed for autostart" unless $check{server} && -x $check{server};
116             }
117              
118 0 0       0 if ($spec->{load_sql}) {
119 0 0 0     0 push @bad => "'mysql' and 'mariadb' commands are missing, needed for load_sql" unless $check{client} && -x $check{client};
120             }
121              
122 0 0 0     0 if (($spec->{bootstrap} || $spec->{autostart}) && $check{server} && -x $check{server}) {
      0        
      0        
123 0 0       0 if (my $broken = $this->broken_version_check($check{server})) {
124 0         0 push @bad => $broken;
125             }
126             }
127             }
128              
129 13 50       23 return (1, undef) unless @bad;
130 13         59 return (0, join "\n" => @bad);
131             }
132              
133             sub bootstrap {
134 0     0     my $self = shift;
135              
136 0           my $init_file = $self->SUPER::bootstrap(@_);
137              
138             # Bootstrap is much faster without InnoDB, we will turn InnoDB back on later, and things will use it.
139 0           $self->write_config(
140             mariadbd => {
141             skip => qr/innodb/i,
142             add => {'default-storage-engine' => 'MyISAM'}
143             },
144             mysqld => {
145             skip => qr/innodb/i,
146             add => {'default-storage-engine' => 'MyISAM'}
147             }
148             );
149 0           $self->run_command([$self->start_command, '--bootstrap'], {stdin => $init_file});
150              
151             # Turn InnoDB back on
152 0           $self->write_config();
153              
154 0           return;
155             }
156              
157             1;
158              
159             __END__