From cfaa470bad31c39dd7537b9592bfb4183a15486f Mon Sep 17 00:00:00 2001 From: Dave Miller Date: Sat, 20 Jun 2026 03:49:06 -0400 Subject: [PATCH] Bug 1917423: undo table conversion mess from bug 1898882 --- Bugzilla/Config.pm | 12 ++++++- Bugzilla/Config/Common.pm | 11 ++++-- Bugzilla/DB/MariaDB.pm | 75 ++++++++++++++++++++++++--------------- Bugzilla/DB/Mysql.pm | 74 ++++++++++++++++++++++++-------------- 4 files changed, 114 insertions(+), 58 deletions(-) diff --git a/Bugzilla/Config.pm b/Bugzilla/Config.pm index bacea397c..8cb010177 100644 --- a/Bugzilla/Config.pm +++ b/Bugzilla/Config.pm @@ -103,6 +103,16 @@ sub update_params { # --- UPDATE OLD PARAMS --- + # Normalize legacy utf8 values to explicit charset names. + if (exists $param->{'utf8'}) { + if ($param->{'utf8'} eq '1') { + $param->{'utf8'} = 'utf8mb4'; + } + elsif ($param->{'utf8'} eq 'utf8') { + $param->{'utf8'} = 'utf8mb3'; + } + } + # Change from usebrowserinfo to defaultplatform/defaultopsys combo if (exists $param->{'usebrowserinfo'}) { if (!$param->{'usebrowserinfo'}) { @@ -217,7 +227,7 @@ sub update_params { $param->{duo_akey} = Bugzilla::Util::generate_random_password(40); } - $param->{'utf8'} = 1 if $new_install; + $param->{'utf8'} = 'utf8mb4' if $new_install; my %oldparams; diff --git a/Bugzilla/Config/Common.pm b/Bugzilla/Config/Common.pm index 14d72115a..aa43d37de 100644 --- a/Bugzilla/Config/Common.pm +++ b/Bugzilla/Config/Common.pm @@ -89,11 +89,18 @@ sub check_email { sub check_utf8 { my ($utf8, $entry) = @_; # You cannot turn off the UTF-8 parameter. - my $current_utf8 = Bugzilla->params->{'utf8'}; if (!$utf8) { return "You cannot disable UTF-8 support."; } - elsif ($current_utf8 eq 'utf8mb3' && $utf8 ne 'utf8mb3' && $utf8 ne 'utf8mb4') { + + my $current_utf8 = Bugzilla->params->{'utf8'}; + $current_utf8 = 'utf8mb4' if !defined $current_utf8 || $current_utf8 eq '1'; + $current_utf8 = 'utf8mb3' if $current_utf8 eq 'utf8'; + + $utf8 = 'utf8mb4' if $utf8 eq '1'; + $utf8 = 'utf8mb3' if $utf8 eq 'utf8'; + + if ($current_utf8 eq 'utf8mb3' && $utf8 ne 'utf8mb3' && $utf8 ne 'utf8mb4') { return "You cannot downgrade from utf8mb3 support, only keep it or change to utf8mb4."; } elsif ($current_utf8 eq 'utf8mb4' && $utf8 ne 'utf8mb4') { diff --git a/Bugzilla/DB/MariaDB.pm b/Bugzilla/DB/MariaDB.pm index 3edc13474..e43952f0e 100644 --- a/Bugzilla/DB/MariaDB.pm +++ b/Bugzilla/DB/MariaDB.pm @@ -28,7 +28,6 @@ extends qw(Bugzilla::DB); use Bugzilla::Constants; use Bugzilla::Install::Util qw(install_string); -use Bugzilla::Config; use Bugzilla::Util; use Bugzilla::Error; use Bugzilla::DB::Schema::MariaDB; @@ -323,11 +322,10 @@ sub bz_setup_database { $self->do("CREATE TABLE `utf8_test` (id tinyint) CHARACTER SET ? COLLATE ?", undef, $charset, $collate); my ($found_collate) = $self->selectrow_array("SELECT TABLE_COLLATION FROM information_schema.TABLES WHERE TABLE_SCHEMA=? AND TABLE_NAME='utf8_test'", undef, $db_name); $self->do("DROP TABLE `utf8_test`"); - my ($found_charset) = ($found_collate =~ m/^([a-z0-9]+)_/); - Bugzilla->params->{'utf8'} = $found_charset; - Bugzilla->params->{'utf8_collate'} = $found_collate; - Bugzilla::Config::write_params(); - # reload these because they get used later. + my ($found_charset) + = defined $found_collate ? ($found_collate =~ m/^([a-z0-9]+)_/) : (); + $self->{detected_utf8_charset} = $found_charset if defined $found_charset; + $self->{detected_utf8_collate} = $found_collate if defined $found_collate; $charset = $self->utf8_charset; $collate = $self->utf8_collate; @@ -852,37 +850,58 @@ sub _fix_defaults { } sub utf8_charset { - return 'utf8mb4' unless Bugzilla->params->{'utf8'}; - return 'utf8mb4' if Bugzilla->params->{'utf8'} eq '1'; - return Bugzilla->params->{'utf8'}; + my ($self) = @_; + if (ref $self && $self->{detected_utf8_charset}) { + return $self->{detected_utf8_charset}; + } + my $param = Bugzilla->params->{'utf8'}; + return 'utf8mb4' unless $param; + return 'utf8mb4' if $param eq '1'; + return 'utf8mb3' if $param eq 'utf8'; + return $param; } sub utf8_collate { - my $charset = utf8_charset(); + my ($self) = @_; + my $charset = $self->utf8_charset; + if (ref $self && $self->{detected_utf8_collate} + && $self->{detected_utf8_collate} =~ /^${charset}_/) + { + return $self->{detected_utf8_collate}; + } return $charset . '_unicode_520_ci' unless Bugzilla->params->{'utf8_collate'}; return $charset . '_unicode_520_ci' unless (Bugzilla->params->{'utf8_collate'} =~ /^${charset}_/); return Bugzilla->params->{'utf8_collate'}; } sub default_row_format { - my ($class, $table) = @_; - my @no_compress = qw( - bug_user_last_visit - cc - email_rates - logincookies - token_data - tokens - ts_error - ts_exitstatus - ts_funcmap - ts_job - ts_note - user_request_log - votes - ); - return 'Dynamic' if any { $table eq $_ } @no_compress; - return 'Compressed'; + my ($self, $table) = @_; + my $charset = $self->utf8_charset; + if (($charset eq 'utf8') || ($charset eq 'utf8mb3')) { + return 'Compact'; + } + elsif ($charset eq 'utf8mb4') { + my @no_compress = qw( + bug_user_last_visit + cc + email_rates + logincookies + token_data + tokens + ts_error + ts_exitstatus + ts_funcmap + ts_job + ts_note + user_request_log + votes + ); + return 'Dynamic' if any { $table eq $_ } @no_compress; + return 'Compressed'; + } + else { + croak "invalid charset: $charset"; + } } sub _alter_db_charset_to_utf8 { diff --git a/Bugzilla/DB/Mysql.pm b/Bugzilla/DB/Mysql.pm index c287a0eb9..32d250ddb 100644 --- a/Bugzilla/DB/Mysql.pm +++ b/Bugzilla/DB/Mysql.pm @@ -28,7 +28,6 @@ extends qw(Bugzilla::DB); use Bugzilla::Constants; use Bugzilla::Install::Util qw(install_string); -use Bugzilla::Config; use Bugzilla::Util; use Bugzilla::Error; use Bugzilla::DB::Schema::Mysql; @@ -324,10 +323,10 @@ sub bz_setup_database { $self->do("CREATE TABLE `utf8_test` (id tinyint) CHARACTER SET ? COLLATE ?", undef, $charset, $collate); my ($found_collate) = $self->selectrow_array("SELECT TABLE_COLLATION FROM information_schema.TABLES WHERE TABLE_SCHEMA=? AND TABLE_NAME='utf8_test'", undef, $db_name); $self->do("DROP TABLE `utf8_test`"); - my ($found_charset) = ($found_collate =~ m/^([a-z0-9]+)_/); - Bugzilla->params->{'utf8'} = $found_charset; - Bugzilla->params->{'utf8_collate'} = $found_collate; - Bugzilla::Config::write_params(); + my ($found_charset) + = defined $found_collate ? ($found_collate =~ m/^([a-z0-9]+)_/) : (); + $self->{detected_utf8_charset} = $found_charset if defined $found_charset; + $self->{detected_utf8_collate} = $found_collate if defined $found_collate; # reload these because they get used later. $charset = $self->utf8_charset; $collate = $self->utf8_collate; @@ -853,37 +852,58 @@ sub _fix_defaults { } sub utf8_charset { - return 'utf8mb4' unless Bugzilla->params->{'utf8'}; - return 'utf8mb4' if Bugzilla->params->{'utf8'} eq '1'; - return Bugzilla->params->{'utf8'}; + my ($self) = @_; + if (ref $self && $self->{detected_utf8_charset}) { + return $self->{detected_utf8_charset}; + } + my $param = Bugzilla->params->{'utf8'}; + return 'utf8mb4' unless $param; + return 'utf8mb4' if $param eq '1'; + return 'utf8mb3' if $param eq 'utf8'; + return $param; } sub utf8_collate { - my $charset = utf8_charset(); + my ($self) = @_; + my $charset = $self->utf8_charset; + if (ref $self && $self->{detected_utf8_collate} + && $self->{detected_utf8_collate} =~ /^${charset}_/) + { + return $self->{detected_utf8_collate}; + } return $charset . '_unicode_520_ci' unless Bugzilla->params->{'utf8_collate'}; return $charset . '_unicode_520_ci' unless (Bugzilla->params->{'utf8_collate'} =~ /^${charset}_/); return Bugzilla->params->{'utf8_collate'}; } sub default_row_format { - my ($class, $table) = @_; - my @no_compress = qw( - bug_user_last_visit - cc - email_rates - logincookies - token_data - tokens - ts_error - ts_exitstatus - ts_funcmap - ts_job - ts_note - user_request_log - votes - ); - return 'Dynamic' if any { $table eq $_ } @no_compress; - return 'Compressed'; + my ($self, $table) = @_; + my $charset = $self->utf8_charset; + if (($charset eq 'utf8') || ($charset eq 'utf8mb3')) { + return 'Compact'; + } + elsif ($charset eq 'utf8mb4') { + my @no_compress = qw( + bug_user_last_visit + cc + email_rates + logincookies + token_data + tokens + ts_error + ts_exitstatus + ts_funcmap + ts_job + ts_note + user_request_log + votes + ); + return 'Dynamic' if any { $table eq $_ } @no_compress; + return 'Compressed'; + } + else { + croak "invalid charset: $charset"; + } } sub _alter_db_charset_to_utf8 {