Commit 8da7f321 authored by justdave%bugzilla.org's avatar justdave%bugzilla.org

Bug 373869: Custom field names must be all lowercase or buglist.cgi sorting throws an error

Patch by mkanat and justdave r=LpSolit,mkanat; a=mkanat
parent b3630da1
...@@ -749,7 +749,7 @@ sub bz_rename_column { ...@@ -749,7 +749,7 @@ sub bz_rename_column {
if ($old_col_exists) { if ($old_col_exists) {
my $already_renamed = $self->bz_column_info($table, $new_name); my $already_renamed = $self->bz_column_info($table, $new_name);
ThrowCodeError('column_rename_conflict', ThrowCodeError('db_rename_conflict',
{ old => "$table.$old_name", { old => "$table.$old_name",
new => "$table.$new_name" }) if $already_renamed; new => "$table.$new_name" }) if $already_renamed;
my @statements = $self->_bz_real_schema->get_rename_column_ddl( my @statements = $self->_bz_real_schema->get_rename_column_ddl(
...@@ -767,6 +767,23 @@ sub bz_rename_column { ...@@ -767,6 +767,23 @@ sub bz_rename_column {
} }
} }
sub bz_rename_table {
my ($self, $old_name, $new_name) = @_;
my $old_table = $self->bz_table_info($old_name);
return if !$old_table;
my $new = $self->bz_table_info($new_name);
ThrowCodeError('db_rename_conflict', { old => $old_name,
new => $new_name }) if $new;
my @sql = $self->_bz_real_schema->get_rename_table_sql($old_name, $new_name);
print get_text('install_table_rename',
{ old => $old_name, new => $new_name }) . "\n"
if Bugzilla->usage_mode == USAGE_MODE_CMDLINE;
$self->do($_) foreach @sql;
$self->_bz_real_schema->rename_table($old_name, $new_name);
$self->_bz_store_real_schema;
}
##################################################################### #####################################################################
# Schema Information Methods # Schema Information Methods
##################################################################### #####################################################################
...@@ -2155,6 +2172,31 @@ that you want to rename ...@@ -2155,6 +2172,31 @@ that you want to rename
=back =back
=item C<bz_rename_table>
=over
=item B<Description>
Renames a table in the database. Does nothing if the table doesn't exist.
Throws an error if the old table exists and there is already a table
with the new name.
=item B<Params>
=over
=item C<$old_name> - The current name of the table.
=item C<$new_name> - What you're renaming the table to.
=back
=item B<Returns> (nothing)
=back
=back =back
=head2 Schema Information Methods =head2 Schema Information Methods
......
...@@ -1911,6 +1911,37 @@ sub get_rename_column_ddl { ...@@ -1911,6 +1911,37 @@ sub get_rename_column_ddl {
. " has not implemented a method."; . " has not implemented a method.";
} }
sub get_rename_table_sql {
=item C<get_rename_table_sql>
=over
=item B<Description>
Gets SQL to rename a table in the database.
=item B<Params>
=over
=item C<$old_name> - The current name of the table.
=item C<$new_name> - The new name of the table.
=back
=item B<Returns>: An array of SQL statements to rename a table.
=back
=cut
my ($self, $old_name, $new_name) = @_;
return ("ALTER TABLE $old_name RENAME TO $new_name");
}
=item C<delete_table($name)> =item C<delete_table($name)>
Description: Deletes a table from this Schema object. Description: Deletes a table from this Schema object.
...@@ -2062,6 +2093,23 @@ sub add_table { ...@@ -2062,6 +2093,23 @@ sub add_table {
} }
} }
sub rename_table {
=item C<rename_table>
Renames a table from C<$old_name> to C<$new_name> in this Schema object.
=cut
my ($self, $old_name, $new_name) = @_;
my $table = $self->get_table_abstract($old_name);
$self->delete_table($old_name);
$self->add_table($new_name, $table);
}
sub delete_column { sub delete_column {
=item C<delete_column($table, $column)> =item C<delete_column($table, $column)>
......
...@@ -92,6 +92,11 @@ sub _initialize { ...@@ -92,6 +92,11 @@ sub _initialize {
sub get_rename_column_ddl { sub get_rename_column_ddl {
my ($self, $table, $old_name, $new_name) = @_; my ($self, $table, $old_name, $new_name) = @_;
if (lc($old_name) eq lc($new_name)) {
# if the only change is a case change, return an empty list, since Pg
# is case-insensitive and will return an error about a duplicate name
return ();
}
my @sql = ("ALTER TABLE $table RENAME COLUMN $old_name TO $new_name"); my @sql = ("ALTER TABLE $table RENAME COLUMN $old_name TO $new_name");
my $def = $self->get_column_abstract($table, $old_name); my $def = $self->get_column_abstract($table, $old_name);
if ($def->{TYPE} =~ /SERIAL/i) { if ($def->{TYPE} =~ /SERIAL/i) {
...@@ -104,6 +109,16 @@ sub get_rename_column_ddl { ...@@ -104,6 +109,16 @@ sub get_rename_column_ddl {
return @sql; return @sql;
} }
sub get_rename_table_sql {
my ($self, $old_name, $new_name) = @_;
if (lc($old_name) eq lc($new_name)) {
# if the only change is a case change, return an empty list, since Pg
# is case-insensitive and will return an error about a duplicate name
return ();
}
return ("ALTER TABLE $old_name RENAME TO $new_name");
}
sub _get_alter_type_sql { sub _get_alter_type_sql {
my ($self, $table, $column, $new_def, $old_def) = @_; my ($self, $table, $column, $new_def, $old_def) = @_;
my @statements; my @statements;
......
...@@ -208,7 +208,7 @@ sub _check_mailhead { return $_[1] ? 1 : 0; } ...@@ -208,7 +208,7 @@ sub _check_mailhead { return $_[1] ? 1 : 0; }
sub _check_name { sub _check_name {
my ($invocant, $name, $is_custom) = @_; my ($invocant, $name, $is_custom) = @_;
$name = clean_text($name); $name = lc(clean_text($name));
$name || ThrowUserError('field_missing_name'); $name || ThrowUserError('field_missing_name');
# Don't want to allow a name that might mess up SQL. # Don't want to allow a name that might mess up SQL.
......
...@@ -503,6 +503,8 @@ sub update_table_definitions { ...@@ -503,6 +503,8 @@ sub update_table_definitions {
$dbh->bz_add_column('milestones', 'id', $dbh->bz_add_column('milestones', 'id',
{TYPE => 'MEDIUMSERIAL', NOTNULL => 1, PRIMARYKEY => 1}); {TYPE => 'MEDIUMSERIAL', NOTNULL => 1, PRIMARYKEY => 1});
_fix_uppercase_custom_field_names();
################################################################ ################################################################
# New --TABLE-- changes should go *** A B O V E *** this point # # New --TABLE-- changes should go *** A B O V E *** this point #
################################################################ ################################################################
...@@ -2732,6 +2734,25 @@ sub _update_longdescs_who_index { ...@@ -2732,6 +2734,25 @@ sub _update_longdescs_who_index {
} }
} }
sub _fix_uppercase_custom_field_names {
# Before the final release of 3.0, custom fields could be
# created with mixed-case names.
my $dbh = Bugzilla->dbh;
my $fields = $dbh->selectall_arrayref(
'SELECT name, type FROM fielddefs WHERE custom = 1');
foreach my $row (@$fields) {
my ($name, $type) = @$row;
if ($name ne lc($name)) {
$dbh->bz_rename_column('bugs', $name, lc($name));
$dbh->bz_rename_table($name, lc($name))
if $type == FIELD_TYPE_SINGLE_SELECT;
$dbh->do('UPDATE fielddefs SET name = ? WHERE name = ?',
undef, lc($name), $name);
}
}
}
1; 1;
__END__ __END__
......
...@@ -118,7 +118,7 @@ ...@@ -118,7 +118,7 @@
without specifying a default or something for $set_nulls_to, because without specifying a default or something for $set_nulls_to, because
there are NULL values currently in it. there are NULL values currently in it.
[% ELSIF error == "column_rename_conflict" %] [% ELSIF error == "db_rename_conflict" %]
Name conflict: Cannot rename [% old FILTER html %] to Name conflict: Cannot rename [% old FILTER html %] to
[% new FILTER html %] because [% new FILTER html %] already exists. [% new FILTER html %] because [% new FILTER html %] already exists.
......
...@@ -394,6 +394,9 @@ ...@@ -394,6 +394,9 @@
[% ELSIF message_tag == "install_table_drop" %] [% ELSIF message_tag == "install_table_drop" %]
Dropping the '[% name FILTER html %]' table... Dropping the '[% name FILTER html %]' table...
[% ELSIF message_tag == "install_table_rename" %]
Renaming the '[% old FILTER html %]' table to '[% new FILTER html %]'...
[% ELSIF message_tag == "install_urlbase_default" %] [% ELSIF message_tag == "install_urlbase_default" %]
Now that you have installed [% terms.Bugzilla %], you should visit the Now that you have installed [% terms.Bugzilla %], you should visit the
'Parameters' page (linked in the footer of the Administrator 'Parameters' page (linked in the footer of the Administrator
......
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