Commit c922073c authored by mkanat%bugzilla.org's avatar mkanat%bugzilla.org

Bug 302876: Database Version-Checking needs to be more modular and more generic

Patch By Max Kanat-Alexander <mkanat@bugzilla.org> r=wicked, a=myk
parent 7adc23f4
...@@ -101,6 +101,8 @@ use base qw(Exporter); ...@@ -101,6 +101,8 @@ use base qw(Exporter);
FIELD_TYPE_FREETEXT FIELD_TYPE_FREETEXT
BUG_STATE_OPEN BUG_STATE_OPEN
DB_MODULE
); );
@Bugzilla::Constants::EXPORT_OK = qw(contenttypes); @Bugzilla::Constants::EXPORT_OK = qw(contenttypes);
...@@ -277,3 +279,13 @@ use constant BUG_STATE_OPEN => ('NEW', 'REOPENED', 'ASSIGNED', ...@@ -277,3 +279,13 @@ use constant BUG_STATE_OPEN => ('NEW', 'REOPENED', 'ASSIGNED',
'UNCONFIRMED'); 'UNCONFIRMED');
1; 1;
# Data about what we require for different databases.
use constant DB_MODULE => {
'mysql' => {db => 'Bugzilla::DB::Mysql', db_version => '4.0.14',
dbd => 'DBD::mysql', dbd_version => '2.9003',
name => 'MySQL'},
'pg' => {db => 'Bugzilla::DB::Pg', db_version => '8.00.0000',
dbd => 'DBD::Pg', dbd_version => '1.45',
name => 'PostgreSQL'},
};
...@@ -48,6 +48,7 @@ use base qw(Exporter DBI::db); ...@@ -48,6 +48,7 @@ use base qw(Exporter DBI::db);
Exporter::export_ok_tags('deprecated'); Exporter::export_ok_tags('deprecated');
use Bugzilla::Config qw(:DEFAULT :db); use Bugzilla::Config qw(:DEFAULT :db);
use Bugzilla::Constants;
use Bugzilla::Util; use Bugzilla::Util;
use Bugzilla::Error; use Bugzilla::Error;
use Bugzilla::DB::Schema; use Bugzilla::DB::Schema;
...@@ -164,14 +165,11 @@ sub connect_main { ...@@ -164,14 +165,11 @@ sub connect_main {
sub _connect { sub _connect {
my ($driver, $host, $dbname, $port, $sock, $user, $pass) = @_; my ($driver, $host, $dbname, $port, $sock, $user, $pass) = @_;
# DB specific module have the same name as DB driver, here we my $pkg_module = DB_MODULE->{lc($driver)}->{db};
# just make sure we are not case sensitive
(my $db_module = $driver) =~ s/(\w+)/\u\L$1/g;
my $pkg_module = "Bugzilla::DB::" . $db_module;
# do the actual import # do the actual import
eval ("require $pkg_module") eval ("require $pkg_module")
|| die ("'$db_module' is not a valid choice for \$db_driver in " || die ("'$driver' is not a valid choice for \$db_driver in "
. " localconfig: " . $@); . " localconfig: " . $@);
# instantiate the correct DB specific module # instantiate the correct DB specific module
...@@ -622,8 +620,9 @@ sub bz_rename_column { ...@@ -622,8 +620,9 @@ sub bz_rename_column {
sub _bz_schema { sub _bz_schema {
my ($self) = @_; my ($self) = @_;
return $self->{private_bz_schema} if exists $self->{private_bz_schema}; return $self->{private_bz_schema} if exists $self->{private_bz_schema};
$self->{private_bz_schema} = my @module_parts = split('::', ref $self);
Bugzilla::DB::Schema->new($self->MODULE_NAME); my $module_name = pop @module_parts;
$self->{private_bz_schema} = Bugzilla::DB::Schema->new($module_name);
return $self->{private_bz_schema}; return $self->{private_bz_schema};
} }
...@@ -989,28 +988,6 @@ constants are required to be subroutines or "use constant" variables. ...@@ -989,28 +988,6 @@ constants are required to be subroutines or "use constant" variables.
The C<\%attr> argument that must be passed to bind_param in order to The C<\%attr> argument that must be passed to bind_param in order to
correctly escape a C<LONGBLOB> type. correctly escape a C<LONGBLOB> type.
=item C<REQUIRED_VERSION>
This is the minimum required version of the database server that the
Bugzilla::DB subclass requires. It should be in a format suitable for
passing to vers_cmp during installation.
=item C<PROGRAM_NAME>
The human-readable name of this database. For example, for MySQL, this
would be 'MySQL.' You should not depend on this variable to know what
type of database you are running on; this is intended merely for displaying
to the admin to let them know what DB they're running.
=item C<MODULE_NAME>
The name of the Bugzilla::DB module that we are. For example, for the MySQL
Bugzilla::DB module, this would be "Mysql." For PostgreSQL it would be "Pg."
=item C<DBD_VERSION>
The minimum version of the DBD module that we require for this database.
=back =back
...@@ -1559,4 +1536,6 @@ PopGlobalSQLState ...@@ -1559,4 +1536,6 @@ PopGlobalSQLState
L<DBI> L<DBI>
L<Bugzilla::Constants> - The C<DB_MODULE> constant.
=cut =cut
...@@ -49,11 +49,6 @@ use Bugzilla::Error; ...@@ -49,11 +49,6 @@ use Bugzilla::Error;
# This module extends the DB interface via inheritance # This module extends the DB interface via inheritance
use base qw(Bugzilla::DB); use base qw(Bugzilla::DB);
use constant REQUIRED_VERSION => '4.0.14';
use constant PROGRAM_NAME => 'MySQL';
use constant MODULE_NAME => 'Mysql';
use constant DBD_VERSION => '2.9003';
sub new { sub new {
my ($class, $user, $pass, $host, $dbname, $port, $sock) = @_; my ($class, $user, $pass, $host, $dbname, $port, $sock) = @_;
......
...@@ -50,10 +50,6 @@ use DBD::Pg; ...@@ -50,10 +50,6 @@ use DBD::Pg;
use base qw(Bugzilla::DB); use base qw(Bugzilla::DB);
use constant BLOB_TYPE => { pg_type => DBD::Pg::PG_BYTEA }; use constant BLOB_TYPE => { pg_type => DBD::Pg::PG_BYTEA };
use constant REQUIRED_VERSION => '8.00.0000';
use constant PROGRAM_NAME => 'PostgreSQL';
use constant MODULE_NAME => 'Pg';
use constant DBD_VERSION => '1.45';
sub new { sub new {
my ($class, $user, $pass, $host, $dbname, $port) = @_; my ($class, $user, $pass, $host, $dbname, $port) = @_;
......
...@@ -376,6 +376,17 @@ foreach my $module (@{$modules}) { ...@@ -376,6 +376,17 @@ foreach my $module (@{$modules}) {
} }
} }
print ("\nYou need one of the following DBD modules installed, depending on\n"
. "which database you are using with Bugzilla:\n") unless $silent;
my $have_one_dbd = 0;
my $db_modules = DB_MODULE;
foreach my $db (keys %$db_modules) {
if (have_vers($db_modules->{$db}->{dbd}, $db_modules->{$db}->{dbd_version})) {
$have_one_dbd = 1;
}
}
print "\nThe following Perl modules are optional:\n" unless $silent; print "\nThe following Perl modules are optional:\n" unless $silent;
my $gd = have_vers("GD","1.20"); my $gd = have_vers("GD","1.20");
my $chartbase = have_vers("Chart::Base","1.0"); my $chartbase = have_vers("Chart::Base","1.0");
...@@ -433,8 +444,23 @@ if (!$patchreader && !$silent) { ...@@ -433,8 +444,23 @@ if (!$patchreader && !$silent) {
print "PatchReader: " . install_command("PatchReader") . "\n"; print "PatchReader: " . install_command("PatchReader") . "\n";
} }
if (%missing) { if (!$have_one_dbd) {
print "\n\n"; print "\n\n";
print "Bugzilla requires that at least one DBD module be installed in\n",
"order to access a database. You can install the correct one by\n",
"picking the command listed below for your database:\n";
foreach my $db (keys %$db_modules) {
print " " . $db_modules->{$db}->{name} . ": "
. install_command($db_modules->{$db}->{dbd}) . "\n";
print " Minimum version required: "
. $db_modules->{$db}->{dbd_version} . "\n";
}
print "\n";
}
if (%missing) {
print "\n";
print "Bugzilla requires some Perl modules which are either missing from\n", print "Bugzilla requires some Perl modules which are either missing from\n",
"your system, or the version on your system is too old.\n", "your system, or the version on your system is too old.\n",
"They can be installed by running (as $::root) the following:\n"; "They can be installed by running (as $::root) the following:\n";
...@@ -445,9 +471,10 @@ if (%missing) { ...@@ -445,9 +471,10 @@ if (%missing) {
} }
} }
print "\n"; print "\n";
exit;
} }
exit if (%missing || !$have_one_dbd);
} }
} }
...@@ -1487,37 +1514,27 @@ $::ENV{'PATH'} = $origPath; ...@@ -1487,37 +1514,27 @@ $::ENV{'PATH'} = $origPath;
# Check if we have access to the --DATABASE-- # Check if we have access to the --DATABASE--
# #
# No need to "use" this here. It should already be loaded from the
# version-checking routines above, and this file won't even compile if
# DBI isn't installed so the user gets nasty errors instead of our
# pretty one saying they need to install it. -- justdave@syndicomm.com
#use DBI;
if ($my_db_check) { if ($my_db_check) {
# Do we have the database itself? # Only certain values are allowed for $db_driver.
if (!exists DB_MODULE->{lc($my_db_driver)}) {
# Unfortunately, $my_db_driver doesn't map perfectly between DBD die "$my_db_driver is not a valid choice for \$db_driver in",
# and Bugzilla::DB. We need to fix the case a bit. " localconfig";
(my $dbd_name = trim($my_db_driver)) =~ s/(\w+)/\u\L$1/g;
# And MySQL is special, because it's all lowercase in DBD.
$dbd_name = 'mysql' if $dbd_name eq 'Mysql';
my $dbd = "DBD::$dbd_name";
unless (eval("require $dbd")) {
print "Bugzilla requires that perl's $dbd be installed.\n"
. "To install this module, you can do:\n "
. " " . install_command($dbd) . "\n";
exit;
} }
my $dbh = Bugzilla::DB::connect_main("no database connection"); # Check the existence and version of the DBD that we need.
my $sql_want = $dbh->REQUIRED_VERSION; my $actual_dbd = DB_MODULE->{lc($my_db_driver)}->{dbd};
my $sql_server = $dbh->PROGRAM_NAME; my $actual_dbd_ver = DB_MODULE->{lc($my_db_driver)}->{dbd_version};
my $dbd_ver = $dbh->DBD_VERSION; my $sql_server = DB_MODULE->{lc($my_db_driver)}->{name};
unless (have_vers($dbd, $dbd_ver)) { my $sql_want = DB_MODULE->{lc($my_db_driver)}->{db_version};
die "Bugzilla requires at least version $dbd_ver of $dbd."; unless (have_vers($actual_dbd, $actual_dbd_ver)) {
print "For $sql_server, Bugzilla requires that perl's"
. " $actual_dbd be installed.\nTo install this module,"
. " you can do:\n " . install_command($actual_dbd) . "\n";
exit;
} }
# And now check the version of the database server itself.
my $dbh = Bugzilla::DB::connect_main("no database connection");
printf("Checking for %15s %-9s ", $sql_server, "(v$sql_want)") unless $silent; printf("Checking for %15s %-9s ", $sql_server, "(v$sql_want)") unless $silent;
my $sql_vers = $dbh->bz_server_version; my $sql_vers = $dbh->bz_server_version;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment