From 441c482ebb5f372b2563044d506e9067cc2e51d0 Mon Sep 17 00:00:00 2001 From: andershol Date: Wed, 24 Jan 2018 21:52:57 -0800 Subject: [PATCH 1/2] Bug 377432: Fix "Building Schema object from database" to handle existing foreign keys --- .gitignore | 1 + Bugzilla/DB.pm | 7 +++--- Bugzilla/DB/Mysql.pm | 49 ++++++++++++++++++++++++++++++------- Bugzilla/DB/Schema.pm | 7 +++--- Bugzilla/DB/Schema/Mysql.pm | 3 +++ 5 files changed, 52 insertions(+), 15 deletions(-) diff --git a/.gitignore b/.gitignore index f64bec8dd..65638f93f 100644 --- a/.gitignore +++ b/.gitignore @@ -29,6 +29,7 @@ /local .DS_Store .vscode/perl-lang +.vagrant/ version.json __lbheartbeat__ .perl-version diff --git a/Bugzilla/DB.pm b/Bugzilla/DB.pm index 1f0daf051..85800f5de 100644 --- a/Bugzilla/DB.pm +++ b/Bugzilla/DB.pm @@ -765,10 +765,11 @@ sub bz_add_fks { sub bz_alter_column { my ($self, $table, $name, $new_def, $set_nulls_to) = @_; - my $current_def = $self->bz_column_info($table, $name); - - if (!$self->_bz_schema->columns_equal($current_def, $new_def)) { + if (!$current_def) { + $self->bz_add_column($table, $name, $new_def, $set_nulls_to); + } + elsif (!$self->_bz_schema->columns_equal($current_def, $new_def)) { # You can't change a column to be NOT NULL if you have no DEFAULT # and no value for $set_nulls_to, if there are any NULL values diff --git a/Bugzilla/DB/Mysql.pm b/Bugzilla/DB/Mysql.pm index 214618031..892efd886 100644 --- a/Bugzilla/DB/Mysql.pm +++ b/Bugzilla/DB/Mysql.pm @@ -1001,18 +1001,49 @@ sub _bz_raw_column_info { # DBD::mysql does not support selecting a specific column, # so we have to get all the columns on the table and find # the one we want. - my $info_sth = $self->column_info(undef, undef, $table, '%'); - - # Don't use fetchall_hashref as there's a Win32 DBI bug (292821) - my $col_data; - while ($col_data = $info_sth->fetchrow_hashref) { - last if $col_data->{'COLUMN_NAME'} eq $column; + my $info_cache = Bugzilla->request_cache->{'column_info_cache'} + || (Bugzilla->request_cache->{'column_info_cache'} = {}); + + if (!defined $info_cache->{$table}) { + # Don't use fetchall_hashref as there's a Win32 DBI bug (292821) + my $info_sth = $self->column_info(undef, undef, $table, '%'); + while (my $col_data = $info_sth->fetchrow_hashref) { + if (!defined $info_cache->{$col_data->{'TABLE_NAME'}}) { + $info_cache->{$col_data->{'TABLE_NAME'}} = {}; + } + $info_cache->{$col_data->{'TABLE_NAME'}}{$col_data->{'COLUMN_NAME'}} = + $col_data; + } } - if (!defined $col_data) { - return undef; + if (!defined Bugzilla->request_cache->{'column_fk_cache'}) { + my $fk_cache = Bugzilla->request_cache->{'column_fk_cache'} = {}; + my $fk_sth = $self->foreign_key_info(undef, undef, undef, undef, undef, + undef); + while (my $fk = $fk_sth->fetchrow_hashref) { + next if !defined $fk->{'PKCOLUMN_NAME'}; + if (!defined $fk_cache->{$fk->{'FKTABLE_NAME'}}) { + $fk_cache->{$fk->{'FKTABLE_NAME'}} = {}; + } + $fk_cache->{$fk->{'FKTABLE_NAME'}}{$fk->{'FKCOLUMN_NAME'}} = $fk; + } + } + my $fk_cache = Bugzilla->request_cache->{'column_fk_cache'}; + + if (defined $info_cache->{$table}{$column}) { + my $col_data = $info_cache->{$table}{$column}; + if (defined $fk_cache->{$table}{$column}) { + my $fk = $fk_cache->{$table}{$column}; + $col_data->{'REFERENCES'} = { + TABLE => $fk->{'PKTABLE_NAME'}, + COLUMN => $fk->{'PKCOLUMN_NAME'}, + DELETE => '', + created => 1, + }; + } + return $col_data; } - return $col_data; + return undef; } =item C diff --git a/Bugzilla/DB/Schema.pm b/Bugzilla/DB/Schema.pm index 6b1f0c0fb..72ea4e6a7 100644 --- a/Bugzilla/DB/Schema.pm +++ b/Bugzilla/DB/Schema.pm @@ -3025,11 +3025,12 @@ Sets the C item on the specified column. sub set_fk { my ($self, $table, $column, $fk_def) = @_; - # Don't want to modify the source def before we explicitly set it below. - # This is just us being extra-cautious. - my $column_def = dclone($self->get_column_abstract($table, $column)); + my $column_def = $self->get_column_abstract($table, $column); die "Tried to set an fk on $table.$column, but that column doesn't exist" if !$column_def; + # Don't want to modify the source def before we explicitly set it below. + # This is just us being extra-cautious. + $column_def = dclone($column_def); if ($fk_def) { $column_def->{REFERENCES} = $fk_def; } diff --git a/Bugzilla/DB/Schema/Mysql.pm b/Bugzilla/DB/Schema/Mysql.pm index 3a807e07f..b418b453e 100644 --- a/Bugzilla/DB/Schema/Mysql.pm +++ b/Bugzilla/DB/Schema/Mysql.pm @@ -314,6 +314,9 @@ sub column_info_to_column { my $col_name = $column_info->{COLUMN_NAME}; my $column = {}; + if (defined $column_info->{REFERENCES}) { + $column->{REFERENCES} = $column_info->{REFERENCES}; + } ($column->{NOTNULL} = 1) if $column_info->{NULLABLE} == 0; From 3bea80c9c8b2a72afc663a6cdd97841c7dc161ce Mon Sep 17 00:00:00 2001 From: Dave Miller Date: Sat, 11 Jul 2026 10:03:26 -0400 Subject: [PATCH 2/2] Add missing DBI proxy forwarder --- Bugzilla/DB.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Bugzilla/DB.pm b/Bugzilla/DB.pm index 85800f5de..c2869747e 100644 --- a/Bugzilla/DB.pm +++ b/Bugzilla/DB.pm @@ -57,7 +57,7 @@ around 'attrs' => sub { # time we need a DBI handle to ensure the connection is alive. { my @DBI_METHODS = qw( - begin_work column_info commit do errstr get_info last_insert_id ping prepare + begin_work column_info commit do errstr foreign_key_info get_info last_insert_id ping prepare primary_key quote_identifier rollback selectall_arrayref selectall_hashref selectcol_arrayref selectrow_array selectrow_arrayref selectrow_hashref table_info );