diff --git a/Bugzilla/Bug.pm b/Bugzilla/Bug.pm index 18bbb08b9..dabd63a73 100644 --- a/Bugzilla/Bug.pm +++ b/Bugzilla/Bug.pm @@ -233,13 +233,9 @@ sub DEPENDENCIES # Product may have classification value_field, but it's not # stored in bugs table so we shouldn't check it next if $deps->{$field->name} || $field->name eq 'product'; - if ($field->visibility_field) + for (qw(visibility_field value_field null_field)) { - $deps->{$field->name}->{$field->visibility_field->name} = 1; - } - if ($field->value_field) - { - $deps->{$field->name}->{$field->value_field->name} = 1; + $deps->{$field->name}->{$field->$_->name} = 1 if $field->$_; } } @@ -3544,8 +3540,7 @@ sub GetBugActivity } my $query = - "SELECT fielddefs.name, a.attach_id, " . - $dbh->sql_date_format('a.bug_when', '%Y.%m.%d %H:%i:%s') . + "SELECT fielddefs.name, a.attach_id, " . $dbh->sql_date_format('a.bug_when') . " bug_when, a.removed, a.added, profiles.login_name, null AS comment_id, null AS comment_count" . " FROM bugs_activity a $suppjoins". " LEFT JOIN fielddefs ON a.fieldid = fielddefs.id". diff --git a/Bugzilla/DB.pm b/Bugzilla/DB.pm index 003cd5c1f..909adee86 100644 --- a/Bugzilla/DB.pm +++ b/Bugzilla/DB.pm @@ -601,14 +601,26 @@ sub bz_add_column { } } -sub bz_add_fk { +sub bz_add_fk +{ my ($self, $table, $column, $def) = @_; + my $check = 1; my $col_def = $self->bz_column_info($table, $column); - if (!$col_def->{REFERENCES}) { - $self->_check_references($table, $column, $def); - print get_text('install_fk_add', - { table => $table, column => $column, fk => $def }) + if ($col_def->{REFERENCES} && (lc($col_def->{REFERENCES}->{DELETE} || 'RESTRICT') ne lc($def->{DELETE} || 'RESTRICT') + || lc($col_def->{REFERENCES}->{UPDATE} || 'CASCADE') ne lc($def->{UPDATE} || 'CASCADE'))) + { + # Fix UPDATE and DELETE actions + $check = 0; + delete $col_def->{REFERENCES}; + print get_text('install_fk_drop', { table => $table, column => $column, fk => $def }) + . "\n" if Bugzilla->usage_mode == USAGE_MODE_CMDLINE; + $self->do($_) foreach $self->_bz_real_schema->get_drop_fk_sql($table, $column, $def); + } + if (!$col_def->{REFERENCES}) + { + $self->_check_references($table, $column, $def) if $check; + print get_text('install_fk_add', { table => $table, column => $column, fk => $def }) . "\n" if Bugzilla->usage_mode == USAGE_MODE_CMDLINE; my @sql = $self->_bz_real_schema->get_add_fk_sql($table, $column, $def); $self->do($_) foreach @sql; @@ -1371,24 +1383,21 @@ sub _bz_real_schema { =cut -sub _bz_store_real_schema { +sub _bz_store_real_schema +{ my ($self) = @_; # Make sure that there's a schema to update - my $table_size = $self->selectrow_array("SELECT COUNT(*) FROM bz_schema"); - - die "Attempted to update the bz_schema table but there's nothing " - . "there to update. Run checksetup." unless $table_size; + $self->_bz_real_schema || die "Attempted to update the bz_schema table but there's nothing there to update. Run checksetup."; # We want to store the current object, not one # that we read from the database. So we use the actual hash # member instead of the subroutine call. If the hash # member is not defined, we will (and should) fail. - my $update_schema = $self->{private_real_schema}; + my $update_schema = $self->_bz_real_schema; my $store_me = $update_schema->serialize_abstract(); my $schema_version = $update_schema->SCHEMA_VERSION; - my $sth = $self->prepare("UPDATE bz_schema - SET schema_data = ?, version = ?"); + my $sth = $self->prepare("UPDATE bz_schema SET schema_data = ?, version = ?"); $sth->bind_param(1, $store_me, $self->BLOB_TYPE); $sth->bind_param(2, $schema_version); $sth->execute(); diff --git a/Bugzilla/DB/Mysql.pm b/Bugzilla/DB/Mysql.pm index f8620566c..fa9146aeb 100644 --- a/Bugzilla/DB/Mysql.pm +++ b/Bugzilla/DB/Mysql.pm @@ -239,7 +239,7 @@ sub sql_to_days { sub sql_date_format { my ($self, $date, $format) = @_; - $format = "%Y.%m.%d %H:%i:%s" if !$format; + $format = "%Y-%m-%d %H:%i:%s" if !$format; return "DATE_FORMAT($date, " . $self->quote($format) . ")"; } diff --git a/Bugzilla/DB/Schema.pm b/Bugzilla/DB/Schema.pm index bcbbf6bc1..2c053cf0c 100644 --- a/Bugzilla/DB/Schema.pm +++ b/Bugzilla/DB/Schema.pm @@ -310,7 +310,7 @@ use constant ABSTRACT_SCHEMA => { id => {TYPE => 'INTSERIAL', NOTNULL => 1, PRIMARYKEY => 1}, bug_id => {TYPE => 'INT4', NOTNULL => 1, REFERENCES => {TABLE => 'bugs', COLUMN => 'bug_id', DELETE => 'CASCADE'}}, attach_id => {TYPE => 'INT4', REFERENCES => {TABLE => 'attachments', COLUMN => 'attach_id', DELETE => 'CASCADE'}}, - who => {TYPE => 'INT4', NOTNULL => 1, REFERENCES => {TABLE => 'profiles', COLUMN => 'userid'}}, + who => {TYPE => 'INT4', NOTNULL => 1, REFERENCES => {TABLE => 'profiles', COLUMN => 'userid', DELETE => 'CASCADE'}}, bug_when => {TYPE => 'DATETIME', NOTNULL => 1}, fieldid => {TYPE => 'INT4', NOTNULL => 1, REFERENCES => {TABLE => 'fielddefs', COLUMN => 'id', DELETE => 'CASCADE'}}, added => {TYPE => 'LONGTEXT'}, @@ -341,7 +341,7 @@ use constant ABSTRACT_SCHEMA => { FIELDS => [ comment_id => {TYPE => 'INTSERIAL', NOTNULL => 1, PRIMARYKEY => 1}, bug_id => {TYPE => 'INT4', NOTNULL => 1, REFERENCES => {TABLE => 'bugs', COLUMN => 'bug_id', DELETE => 'CASCADE'}}, - who => {TYPE => 'INT4', NOTNULL => 1, REFERENCES => {TABLE => 'profiles', COLUMN => 'userid'}}, + who => {TYPE => 'INT4', NOTNULL => 1, REFERENCES => {TABLE => 'profiles', COLUMN => 'userid', DELETE => 'CASCADE'}}, bug_when => {TYPE => 'DATETIME', NOTNULL => 1}, work_time => {TYPE => 'decimal(7,2)', NOTNULL => 1, DEFAULT => '0'}, thetext => {TYPE => 'LONGTEXT', NOTNULL => 1}, @@ -362,8 +362,8 @@ use constant ABSTRACT_SCHEMA => { # Editable comments (CustIS Bug 134368) longdescs_history => { FIELDS => [ - bug_id => { TYPE => 'INT4', NOTNULL => 1, REFERENCES => { TABLE => 'bugs', COLUMN => 'bug_id' } }, - who => { TYPE => 'INT4', NOTNULL => 1, REFERENCES => { TABLE => 'profiles', COLUMN => 'userid' } }, + bug_id => { TYPE => 'INT4', NOTNULL => 1, REFERENCES => { TABLE => 'bugs', COLUMN => 'bug_id', DELETE => 'CASCADE' } }, + who => { TYPE => 'INT4', NOTNULL => 1, REFERENCES => { TABLE => 'profiles', COLUMN => 'userid', DELETE => 'CASCADE' } }, bug_when => { TYPE => 'DATETIME', NOTNULL => 1 }, oldthetext => { TYPE => 'LONGTEXT', NOTNULL => 1 }, thetext => { TYPE => 'LONGTEXT', NOTNULL => 1 }, @@ -733,7 +733,7 @@ use constant ABSTRACT_SCHEMA => { FIELDS => [ id => {TYPE => 'INTSERIAL', NOTNULL => 1, PRIMARYKEY => 1}, userid => {TYPE => 'INT4', NOTNULL => 1, REFERENCES => {TABLE => 'profiles', COLUMN => 'userid', DELETE => 'CASCADE'}}, - who => {TYPE => 'INT4', NOTNULL => 1, REFERENCES => {TABLE => 'profiles', COLUMN => 'userid'}}, + who => {TYPE => 'INT4', NOTNULL => 1, REFERENCES => {TABLE => 'profiles', COLUMN => 'userid', DELETE => 'CASCADE'}}, profiles_when => {TYPE => 'DATETIME', NOTNULL => 1}, fieldid => {TYPE => 'INT4', NOTNULL => 1, REFERENCES => {TABLE => 'fielddefs', COLUMN => 'id'}}, oldvalue => {TYPE => 'TINYTEXT'}, @@ -773,7 +773,7 @@ use constant ABSTRACT_SCHEMA => { emailin_aliases => { FIELDS => [ address => {TYPE => 'varchar(255)', NOTNULL => 1}, - userid => {TYPE => 'INT4', NOTNULL => 1, REFERENCES => {TABLE => 'profiles', COLUMN => 'userid'}}, + userid => {TYPE => 'INT4', NOTNULL => 1, REFERENCES => {TABLE => 'profiles', COLUMN => 'userid', DELETE => 'CASCADE'}}, fromldap => {TYPE => 'BOOLEAN'}, isprimary => {TYPE => 'BOOLEAN'}, ], @@ -796,7 +796,7 @@ use constant ABSTRACT_SCHEMA => { namedqueries => { FIELDS => [ id => {TYPE => 'INTSERIAL', NOTNULL => 1, PRIMARYKEY => 1}, - userid => {TYPE => 'INT4', NOTNULL => 1, REFERENCES => {TABLE => 'profiles', COLUMN => 'userid', DELETE => 'CASCADE'}}, + userid => {TYPE => 'INT4', NOTNULL => 1, REFERENCES => {TABLE => 'profiles', COLUMN => 'userid', DELETE => 'CASCADE'}}, name => {TYPE => 'varchar(255)', NOTNULL => 1}, query => {TYPE => 'LONGTEXT', NOTNULL => 1}, ], @@ -810,7 +810,7 @@ use constant ABSTRACT_SCHEMA => { FIELDS => [ id => {TYPE => 'INTSERIAL', NOTNULL => 1, PRIMARYKEY => 1}, query_id => {TYPE => 'INT4', NOTNULL => 1, REFERENCES => {TABLE => 'namedqueries', COLUMN => 'id'}}, - user_id => {TYPE => 'INT4', REFERENCES => {TABLE => 'profiles', COLUMN => 'userid'}}, + user_id => {TYPE => 'INT4', REFERENCES => {TABLE => 'profiles', COLUMN => 'userid', DELETE => 'SET NULL'}}, flags => {TYPE => 'INT2', NOTNULL => 1, DEFAULT => 0}, message => {TYPE => 'LONGTEXT', NOTNULL => 1}, sql_code => {TYPE => 'LONGTEXT'}, @@ -849,7 +849,7 @@ use constant ABSTRACT_SCHEMA => { reports => { FIELDS => [ id => {TYPE => 'INTSERIAL', NOTNULL => 1, PRIMARYKEY => 1}, - user_id => {TYPE => 'INT4', NOTNULL => 1, REFERENCES => {TABLE => 'profiles', COLUMN => 'userid', DELETE => 'CASCADE'}}, + user_id => {TYPE => 'INT4', NOTNULL => 1, REFERENCES => {TABLE => 'profiles', COLUMN => 'userid', DELETE => 'CASCADE'}}, name => {TYPE => 'varchar(255)', NOTNULL => 1}, query => {TYPE => 'LONGTEXT', NOTNULL => 1}, ], @@ -891,9 +891,9 @@ use constant ABSTRACT_SCHEMA => { ip_addr => {TYPE => 'varchar(40)', NOTNULL => 1}, ], INDEXES => [ - # We do lookups by every item in the table simultaneously, but + # We do lookups by every item in the table simultaneously, but # having an index with all three items would be the same size as - # the table. So instead we have an index on just the smallest item, + # the table. So instead we have an index on just the smallest item, # to speed lookups. login_failure_user_id_idx => ['user_id'], ], @@ -905,7 +905,7 @@ use constant ABSTRACT_SCHEMA => { # for these changes. tokens => { FIELDS => [ - userid => {TYPE => 'INT4', REFERENCES => {TABLE => 'profiles', COLUMN => 'userid', DELETE => 'CASCADE'}}, + userid => {TYPE => 'INT4', REFERENCES => {TABLE => 'profiles', COLUMN => 'userid', DELETE => 'CASCADE'}}, issuedate => {TYPE => 'DATETIME', NOTNULL => 1}, token => {TYPE => 'varchar(16)', NOTNULL => 1, PRIMARYKEY => 1}, tokentype => {TYPE => 'varchar(8)', NOTNULL => 1}, @@ -961,7 +961,6 @@ use constant ABSTRACT_SCHEMA => { # if GRANT_REGEXP - record was created by evaluating a regexp user_group_map => { FIELDS => [ - user_id => {TYPE => 'INT4', NOTNULL => 1, REFERENCES => {TABLE => 'profiles', COLUMN => 'userid', DELETE => 'CASCADE'}}, group_id => {TYPE => 'INT4', NOTNULL => 1, REFERENCES => {TABLE => 'groups', COLUMN => 'id', DELETE => 'CASCADE'}}, isbless => {TYPE => 'BOOLEAN', NOTNULL => 1, DEFAULT => 'FALSE'}, grant_type => {TYPE => 'INT1', NOTNULL => 1, DEFAULT => GRANT_DIRECT}, @@ -1006,18 +1005,11 @@ use constant ABSTRACT_SCHEMA => { # in order to see a named query somebody else shares. namedquery_group_map => { FIELDS => [ - namedquery_id => {TYPE => 'INT4', NOTNULL => 1, - REFERENCES => {TABLE => 'namedqueries', - COLUMN => 'id', - DELETE => 'CASCADE'}}, - group_id => {TYPE => 'INT4', NOTNULL => 1, - REFERENCES => {TABLE => 'groups', - COLUMN => 'id', - DELETE => 'CASCADE'}}, + namedquery_id => {TYPE => 'INT4', NOTNULL => 1, REFERENCES => {TABLE => 'namedqueries', COLUMN => 'id', DELETE => 'CASCADE'}}, + group_id => {TYPE => 'INT4', NOTNULL => 1, REFERENCES => {TABLE => 'groups', COLUMN => 'id', DELETE => 'CASCADE'}}, ], INDEXES => [ - namedquery_group_map_namedquery_id_idx => - {FIELDS => [qw(namedquery_id)], TYPE => 'UNIQUE'}, + namedquery_group_map_namedquery_id_idx => {FIELDS => [qw(namedquery_id)], TYPE => 'UNIQUE'}, namedquery_group_map_group_id_idx => ['group_id'], ], }, diff --git a/Bugzilla/Field.pm b/Bugzilla/Field.pm index 60debb5d5..3a674132f 100644 --- a/Bugzilla/Field.pm +++ b/Bugzilla/Field.pm @@ -1337,7 +1337,7 @@ sub update_control_lists $controlling_value_id = Bugzilla->get_field($controlling_field_id)->value_type->new($controlling_value_id); $controlling_value_id = $controlling_value_id ? $controlling_value_id->id : return undef; # Save all visible, nullable and clone flags at once - my $mod = {}; + my $mod = { del => [], add => [] }; for my $f (Bugzilla->get_fields({ obsolete => 0, visibility_field_id => $controlling_field_id })) { push @{$mod->{$params->{'is_visible_'.$f->name} ? 'add' : 'del'}}, [ $f->id, FLAG_VISIBLE ]; @@ -1367,7 +1367,7 @@ sub update_control_lists } # Save all dependent defaults at once my $touched = { map { $_->[0] => 1 } (@{$mod->{add}}, @{$mod->{del}}) }; - $mod = {}; + $mod = { del => [], add => [] }; for my $f (Bugzilla->get_fields({ obsolete => 0, default_field_id => $controlling_field_id })) { next if $f eq 'version' || $f eq 'target_milestone'; # FIXME: default version is hardcoded to depend on component, default milestone is hardcoded to depend on product diff --git a/Bugzilla/Install/DB.pm b/Bugzilla/Install/DB.pm index 255d30510..528c27134 100644 --- a/Bugzilla/Install/DB.pm +++ b/Bugzilla/Install/DB.pm @@ -821,15 +821,6 @@ WHERE description LIKE\'%[CC:%\''); ); } - # Fix bugs_activity.fieldid foreign key - { - my $fk = $dbh->bz_fk_info('bugs_activity', 'fieldid'); - if ($fk && (!$fk->{DELETE} || $fk->{DELETE} ne 'CASCADE')) - { - $dbh->bz_drop_fk('bugs_activity', 'fieldid'); - } - } - # Varchar is VARIABLE, it's generally pointless to set a size limit less than 255 chars for it _set_varchar_255(); @@ -3458,22 +3449,14 @@ sub _convert_multiselects } } -sub _add_foreign_keys_to_multiselects { +sub _add_foreign_keys_to_multiselects +{ my $dbh = Bugzilla->dbh; - - my $names = $dbh->selectcol_arrayref( - 'SELECT name - FROM fielddefs - WHERE type = ' . FIELD_TYPE_MULTI_SELECT); - - foreach my $name (@$names) { - $dbh->bz_add_fk("bug_$name", "bug_id", {TABLE => 'bugs', - COLUMN => 'bug_id', - DELETE => 'CASCADE',}); - - $dbh->bz_add_fk("bug_$name", "value_id", {TABLE => $name, - COLUMN => 'id', - DELETE => 'RESTRICT',}); + my $names = $dbh->selectcol_arrayref('SELECT name FROM fielddefs WHERE type=' . FIELD_TYPE_MULTI_SELECT); + foreach my $name (@$names) + { + $dbh->bz_add_fk("bug_$name", "bug_id", {TABLE => 'bugs', COLUMN => 'bug_id', DELETE => 'CASCADE'}); + $dbh->bz_add_fk("bug_$name", "value_id", {TABLE => $name, COLUMN => 'id', DELETE => 'CASCADE'}); } } diff --git a/editusers.cgi b/editusers.cgi index c858f74ff..287ca5833 100755 --- a/editusers.cgi +++ b/editusers.cgi @@ -521,35 +521,11 @@ if ($action eq 'search') { $updatedbugs{$bug_id} = 1; } - # Simple deletions in referred tables. - $dbh->do('DELETE FROM email_setting WHERE user_id = ?', undef, - $otherUserID); - $dbh->do('DELETE FROM logincookies WHERE userid = ?', undef, $otherUserID); - $dbh->do('DELETE FROM namedqueries WHERE userid = ?', undef, $otherUserID); - $dbh->do('DELETE FROM namedqueries_link_in_footer WHERE user_id = ?', undef, - $otherUserID); - if ($namedqueries_as_string) { - $dbh->do('DELETE FROM namedquery_group_map WHERE namedquery_id IN ' . - "($namedqueries_as_string)"); - } - $dbh->do('DELETE FROM profile_setting WHERE user_id = ?', undef, - $otherUserID); - $dbh->do('DELETE FROM profiles_activity WHERE userid = ? OR who = ?', undef, - ($otherUserID, $otherUserID)); - $dbh->do('DELETE FROM tokens WHERE userid = ?', undef, $otherUserID); - $dbh->do('DELETE FROM user_group_map WHERE user_id = ?', undef, - $otherUserID); - $dbh->do('DELETE FROM votes WHERE who = ?', undef, $otherUserID); - $dbh->do('DELETE FROM watch WHERE watcher = ? OR watched = ?', undef, - ($otherUserID, $otherUserID)); - # Deletions in referred tables which need LogActivityEntry. - my $buglist = $dbh->selectcol_arrayref('SELECT bug_id FROM cc WHERE who = ?', - undef, $otherUserID); + my $buglist = $dbh->selectcol_arrayref('SELECT bug_id FROM cc WHERE who = ?', undef, $otherUserID); $dbh->do('DELETE FROM cc WHERE who = ?', undef, $otherUserID); foreach my $bug_id (@$buglist) { - LogActivityEntry($bug_id, 'cc', $otherUser->login, '', $userid, - $timestamp); + LogActivityEntry($bug_id, 'cc', $otherUser->login, '', $userid, $timestamp); $sth_set_bug_timestamp->execute($timestamp, $bug_id); $updatedbugs{$bug_id} = 1; } @@ -557,40 +533,6 @@ if ($action eq 'search') { # Even more complex deletions in referred tables. my $id; - # 1) Series - my $sth_seriesid = $dbh->prepare( - 'SELECT series_id FROM series WHERE creator = ?'); - my $sth_deleteSeries = $dbh->prepare( - 'DELETE FROM series WHERE series_id = ?'); - my $sth_deleteSeriesData = $dbh->prepare( - 'DELETE FROM series_data WHERE series_id = ?'); - - $sth_seriesid->execute($otherUserID); - while ($id = $sth_seriesid->fetchrow_array()) { - $sth_deleteSeriesData->execute($id); - $sth_deleteSeries->execute($id); - } - - # 2) Whines - my $sth_whineidFromEvents = $dbh->prepare( - 'SELECT id FROM whine_events WHERE owner_userid = ?'); - my $sth_deleteWhineEvent = $dbh->prepare( - 'DELETE FROM whine_events WHERE id = ?'); - my $sth_deleteWhineQuery = $dbh->prepare( - 'DELETE FROM whine_queries WHERE eventid = ?'); - my $sth_deleteWhineSchedule = $dbh->prepare( - 'DELETE FROM whine_schedules WHERE eventid = ?'); - - $dbh->do('DELETE FROM whine_schedules WHERE mailto = ? AND mailto_type = ?', - undef, ($otherUserID, MAILTO_USER)); - - $sth_whineidFromEvents->execute($otherUserID); - while ($id = $sth_whineidFromEvents->fetchrow_array()) { - $sth_deleteWhineQuery->execute($id); - $sth_deleteWhineSchedule->execute($id); - $sth_deleteWhineEvent->execute($id); - } - # 3) Bugs # 3.1) fall back to the default assignee $buglist = $dbh->selectall_arrayref( diff --git a/template/en/default/admin/users/confirm-delete.html.tmpl b/template/en/default/admin/users/confirm-delete.html.tmpl index b61a99541..71c224613 100644 --- a/template/en/default/admin/users/confirm-delete.html.tmpl +++ b/template/en/default/admin/users/confirm-delete.html.tmpl @@ -68,7 +68,7 @@ Group set: [% IF otheruser.groups.size %] -