diff --git a/status/query-monitor.pl b/status/query-monitor.pl index 994977f30..fba8c38c6 100755 --- a/status/query-monitor.pl +++ b/status/query-monitor.pl @@ -1,30 +1,69 @@ # query-monitor.pl -# Try an SQL query on a MySQL or PostgreSQL server +# Try an SQL query on a database server -my %allowed_query_drivers = map { $_, 1 } ("mysql", "Pg", "Oracle"); +# SQL drivers offered in the UI and permitted by strict validation. +my @query_driver_options = ( + [ "mysql", "MySQL" ], + [ "MariaDB", "MariaDB" ], + [ "Pg", "PostgreSQL" ], + [ "Oracle", "Oracle" ] + ); +my %allowed_query_drivers = map { $_->[0], 1 } @query_driver_options; +# canonical_query_driver(driver) +# Normalize a stored driver name to the canonical DBI driver key. +sub canonical_query_driver +{ +my ($driver) = @_; +# Accept legacy lowercase value while storing/using canonical DBI name. +return $driver eq 'mariadb' ? 'MariaDB' : $driver; +} + +# query_driver_candidates(driver) +# Returns preferred and fallback DBI driver names for the selected driver. +sub query_driver_candidates +{ +my ($driver) = @_; +$driver = &canonical_query_driver($driver); +# Match mysql/mysql-lib.pl behavior : prefer selected family, then fallback. +return ($driver eq 'mysql') ? ( "mysql", "MariaDB" ) : + ($driver eq 'MariaDB') ? ( "MariaDB", "mysql" ) : + ( $driver ); +} + +# get_query_status(&service) +# Attempts DB connect and query execution and returns monitor status hash. sub get_query_status { -if (!$allowed_query_drivers{$_[0]->{'driver'}}) { +my $driver = &canonical_query_driver($_[0]->{'driver'}); +if (!$allowed_query_drivers{$driver}) { return { 'up' => -1, 'desc' => &text('query_edriver', - "DBD::$_[0]->{'driver'}") }; + "DBD::$driver") }; } # Load the driver local $drh; -eval <install_driver(\$_[0]->{'driver'}); -EOF +eval { require DBI; }; if ($@) { return { 'up' => -1, 'desc' => &text('query_edriver', - "DBD::$_[0]->{'driver'}") }; + "DBD::$driver") }; + } +my @drivers = &query_driver_candidates($driver); +# Try fallback-compatible drivers to tolerate either DBD::mysql or DBD::MariaDB. +foreach my $try (@drivers) { + eval { $drh = DBI->install_driver($try); }; + last if (!$@ && $drh); + } +if (!$drh) { + return { 'up' => -1, + 'desc' => &text('query_edriver', + "DBD::$driver") }; } # Connect to the database server -local $dbistr = &make_dbistr($_[0]->{'driver'}, $_[0]->{'db'}, $_[0]->{'host'}); +local $dbistr = &make_dbistr($driver, $_[0]->{'db'}, $_[0]->{'host'}); local $dbh = $drh->connect($dbistr, $_[0]->{'user'}, $_[0]->{'pass'}, { }); if (!$dbh) { @@ -53,13 +92,13 @@ if ($_[0]->{'result'} ne '' && $r[0] ne $_[0]->{'result'}) { return { 'up' => 1 }; } +# show_query_dialog(&service) +# Displays the SQL query monitor configuration form fields. sub show_query_dialog { print &ui_table_row($text{'query_driver'}, - &ui_select("driver", $_[0]->{'driver'}, - [ [ "mysql", "MySQL" ], - [ "Pg", "PostgreSQL" ], - [ "Oracle", "Oracle" ] ])); + &ui_select("driver", &canonical_query_driver($_[0]->{'driver'}), + \@query_driver_options)); print &ui_table_row($text{'query_db'}, &ui_textbox("db", $_[0]->{'db'}, 20)); @@ -81,16 +120,26 @@ print &ui_table_row($text{'query_result'}, $text{'query_ignore'}), 3); } +# parse_query_dialog(&service) +# Validates query monitor inputs and stores normalized settings. sub parse_query_dialog { -$allowed_query_drivers{$in{'driver'}} || - &error(&text('query_edriver', "DBD::$in{'driver'}")); -eval { - require DBI; - DBI->install_driver($in{'driver'}); - }; -&error(&text('query_edriver', "DBD::$in{'driver'}")) if ($@); -$_[0]->{'driver'} = $in{'driver'}; +my $driver = &canonical_query_driver($in{'driver'}); +$allowed_query_drivers{$driver} || + &error(&text('query_edriver', "DBD::$driver")); +eval { require DBI; }; +&error(&text('query_edriver', "DBD::$driver")) if ($@); +my $ok; +foreach my $try (&query_driver_candidates($driver)) { + # Validation mirrors runtime loading : any valid fallback driver is accepted. + eval { DBI->install_driver($try); }; + if (!$@) { + $ok = 1; + last; + } + } +&error(&text('query_edriver', "DBD::$driver")) if (!$ok); +$_[0]->{'driver'} = $driver; $in{'db'} =~ /^\S+$/ || &error($text{'query_edb'}); $_[0]->{'db'} = $in{'db'}; @@ -122,11 +171,14 @@ else { } } +# make_dbistr(driver, database, host) +# Builds the DBI connection string for the selected SQL driver. sub make_dbistr { local ($driver, $db, $host) = @_; local $rv; -if ($driver eq "mysql") { +if ($driver eq "mysql" || $driver eq "MariaDB") { + # Both DBI drivers use "database=" style DSN here. $rv = "database=$db"; } elsif ($driver eq "Pg") { @@ -140,5 +192,3 @@ if ($host) { } return $rv; } - -