From e7ba6d75bc128addbcdb04c5bb975e107e0d42c2 Mon Sep 17 00:00:00 2001 From: "mkanat%bugzilla.org" <> Date: Thu, 14 Feb 2008 12:15:16 +0000 Subject: Bug 374951: Handle different strange situations in installations and upgrades that can leave you with a half-latin half-utf8 DB. Patch By Max Kanat-Alexander r=LpSolit, a=mkanat --- Bugzilla/DB/Mysql.pm | 64 ++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 50 insertions(+), 14 deletions(-) diff --git a/Bugzilla/DB/Mysql.pm b/Bugzilla/DB/Mysql.pm index 720c8ff42..2da0c44ea 100644 --- a/Bugzilla/DB/Mysql.pm +++ b/Bugzilla/DB/Mysql.pm @@ -290,17 +290,8 @@ EOT } } - - # There is a bug in MySQL 4.1.0 - 4.1.15 that makes certain SELECT - # statements fail after a SHOW TABLE STATUS: - # http://bugs.mysql.com/bug.php?id=13535 - # This is a workaround, a dummy SELECT to reset the LAST_INSERT_ID. - if (grep($_ eq 'bugs', @tables) - && $self->bz_column_info_real("bugs", "bug_id")) - { - $self->do('SELECT 1 FROM bugs WHERE bug_id IS NULL'); - } - + $self->_after_table_status(\@tables); + # Versions of Bugzilla before the existence of Bugzilla::DB::Schema did # not provide explicit names for the table indexes. This means # that our upgrades will not be reliable, because we look for the name @@ -470,6 +461,17 @@ EOT } # foreach table } # if old-name indexes + # If there are no tables, but the DB isn't utf8 and it should be, + # then we should alter the database to be utf8. We know it should be + # if the utf8 parameter is true or there are no params at all. + # This kind of situation happens when people create the database + # themselves, and if we don't do this they will get the big + # scary WARNING statement about conversion to UTF8. + if ( !$self->bz_db_is_utf8 && !@tables + && (Bugzilla->params->{'utf8'} || !scalar keys %{Bugzilla->params}) ) + { + $self->_alter_db_charset_to_utf8(); + } # And now we create the tables and the Schema object. $self->SUPER::bz_setup_database(); @@ -564,7 +566,16 @@ EOT } # Convert the database to UTF-8 if the utf8 parameter is on. - if (Bugzilla->params->{'utf8'} && !$self->bz_db_is_utf8) { + # We check if any table isn't utf8, because lots of crazy + # partial-conversion situations can happen, and this handles anything + # that could come up (including having the DB charset be utf8 but not + # the table charsets. + my $utf_table_status = + $self->selectall_arrayref("SHOW TABLE STATUS", {Slice=>{}}); + $self->_after_table_status([map($_->{Name}, @$utf_table_status)]); + my @non_utf8_tables = grep($_->{Collation} !~ /^utf8/, @$utf_table_status); + + if (Bugzilla->params->{'utf8'} && scalar @non_utf8_tables) { print <do("ALTER TABLE $table DEFAULT CHARACTER SET utf8"); } # foreach my $table (@tables) + } - my $db_name = Bugzilla->localconfig->{db_name}; - $self->do("ALTER DATABASE $db_name CHARACTER SET utf8"); + # Sometimes you can have a situation where all the tables are utf8, + # but the database isn't. (This tends to happen when you've done + # a mysqldump.) So we have this change outside of the above block, + # so that it just happens silently if no actual *table* conversion + # needs to happen. + if (Bugzilla->params->{'utf8'} && !$self->bz_db_is_utf8) { + $self->_alter_db_charset_to_utf8(); } } +# There is a bug in MySQL 4.1.0 - 4.1.15 that makes certain SELECT +# statements fail after a SHOW TABLE STATUS: +# http://bugs.mysql.com/bug.php?id=13535 +# This is a workaround, a dummy SELECT to reset the LAST_INSERT_ID. +sub _after_table_status { + my ($self, $tables) = @_; + if (grep($_ eq 'bugs', @$tables) + && $self->bz_column_info_real("bugs", "bug_id")) + { + $self->do('SELECT 1 FROM bugs WHERE bug_id IS NULL'); + } +} + +sub _alter_db_charset_to_utf8 { + my $self = shift; + my $db_name = Bugzilla->localconfig->{db_name}; + $self->do("ALTER DATABASE $db_name CHARACTER SET utf8"); +} + sub bz_db_is_utf8 { my $self = shift; my $db_collation = $self->selectrow_arrayref( -- cgit v1.2.3-24-g4f1b