diff options
-rw-r--r-- | Bugzilla/DB.pm | 56 | ||||
-rw-r--r-- | Bugzilla/DB/Schema.pm | 141 | ||||
-rw-r--r-- | Bugzilla/DB/Schema/Mysql.pm | 5 |
3 files changed, 181 insertions, 21 deletions
diff --git a/Bugzilla/DB.pm b/Bugzilla/DB.pm index 292925a6f..2168e6ae4 100644 --- a/Bugzilla/DB.pm +++ b/Bugzilla/DB.pm @@ -392,6 +392,23 @@ sub bz_add_field ($$$) { ADD COLUMN $field $definition"); } +sub bz_add_index { + my ($self, $table, $name, $definition) = @_; + + my $index_exists = $self->bz_index_info($table, $name); + + if (!$index_exists) { + my @statements = $self->_bz_real_schema->get_add_index_ddl( + $table, $name, $definition); + print "Adding new index '$name' to the $table table ...\n"; + foreach my $sql (@statements) { + $self->do($sql); + } + $self->_bz_real_schema->set_index($table, $name, $definition); + $self->_bz_store_real_schema; + } +} + # XXX - Need to make this cross-db compatible # XXX - This shouldn't print stuff to stdout sub bz_change_field_type ($$$) { @@ -430,6 +447,23 @@ sub bz_drop_field ($$) { DROP COLUMN $field"); } +sub bz_drop_index { + my ($self, $table, $name) = @_; + + my $index_exists = $self->bz_index_info($table, $name); + + if ($index_exists) { + my @statements = $self->_bz_real_schema->get_drop_index_ddl( + $table, $name); + print "Removing index '$name' from the $table table...\n"; + foreach my $sql (@statements) { + $self->do($sql); + } + $self->_bz_real_schema->delete_index($table, $name); + $self->_bz_store_real_schema; + } +} + # XXX - Needs to be made cross-db compatible sub bz_drop_table_indexes ($) { my ($self, $table) = @_; @@ -778,6 +812,8 @@ Bugzilla::DB - Database access routines, using L<DBI> # Schema Modification $dbh->bz_add_column($table, $name, \%definition); + $dbh->bz_add_index($table, $name, $definition); + $dbh->bz_drop_index($table, $name); # Schema Modification (DEPRECATED) $dbh->bz_add_field($table, $column, $definition); @@ -1097,6 +1133,26 @@ C<Bugzilla::DB::Schema::ABSTRACT_SCHEMA>. \%definition = Abstract column definition for the new column Returns: nothing +=item C<bz_add_index($table, $name, $definition)> + + Description: Adds a new index to a table in the database. Prints + out a brief statement that it did so, to stdout. + If the index already exists, we will do nothing. + Params: $table - The table the new index is on. + $name - A name for the new index. + $definition - An abstract index definition. + Either a hashref or an arrayref. + Returns: nothing + +=item C<bz_drop_index($table, $name)> + + Description: Removes an index from the database. Prints out a brief + statement that it did so, to stdout. If the index + doesn't exist, we do nothing. + Params: $table - The table that the index is on. + $name - The name of the index that you want to drop. + Returns: nothing + =back diff --git a/Bugzilla/DB/Schema.pm b/Bugzilla/DB/Schema.pm index 525ab99f6..801f353d7 100644 --- a/Bugzilla/DB/Schema.pm +++ b/Bugzilla/DB/Schema.pm @@ -1276,18 +1276,8 @@ sub get_table_ddl { while (@indexes) { my $index_name = shift(@indexes); my $index_info = shift(@indexes); - my($index_fields,$index_type); - if (ref($index_info) eq 'HASH') { - $index_fields = $index_info->{FIELDS}; - $index_type = $index_info->{TYPE}; - } else { - $index_fields = $index_info; - $index_type = ''; - } - my $index_sql = $self->_get_create_index_ddl($table, - $index_name, - $index_fields, - $index_type); + my $index_sql = $self->get_add_index_ddl($table, $index_name, + $index_info); push(@ddl, $index_sql) if $index_sql; } @@ -1378,6 +1368,40 @@ sub get_add_column_ddl { return ($statement); } +sub get_add_index_ddl { + +=item C<get_add_index_ddl> + + Description: Gets SQL for creating an index. + NOTE: Subclasses should not override this function. Instead, + if they need to specify a custom CREATE INDEX statement, + they should override C<_get_create_index_ddl> + Params: $table - The name of the table the index will be on. + $name - The name of the new index. + $definition - An index definition. Either a hashref + with FIELDS and TYPE or an arrayref + containing a list of columns. + Returns: An array of SQL statements that will create the + requested index. + +=cut + + my ($self, $table, $name, $definition) = @_; + + my ($index_fields, $index_type); + # Index defs can be arrays or hashes + if (ref($definition) eq 'HASH') { + $index_fields = $definition->{FIELDS}; + $index_type = $definition->{TYPE}; + } else { + $index_fields = $definition; + $index_type = ''; + } + + return $self->_get_create_index_ddl($table, $name, $index_fields, + $index_type); +} + sub get_alter_column_ddl { =item C<get_alter_ddl($table, $column, \%definition)> @@ -1468,6 +1492,23 @@ sub get_alter_column_ddl { return @statements; } +sub get_drop_index_ddl { + +=item C<get_drop_index_ddl($table, $name)> + + Description: Generates SQL statements to drop an index. + Params: $table - The table the index is on. + $name - The name of the index being dropped. + Returns: An array of SQL statements. + +=cut + my ($self, $table, $name) = @_; + + # Although ANSI SQL-92 doesn't specify a method of dropping an index, + # many DBs support this syntax. + return ("DROP INDEX $name"); +} + sub get_column_abstract { =item C<get_column_abstract($table, $column)> @@ -1513,7 +1554,7 @@ sub get_index_abstract { # table doesn't exist. if (exists $self->{abstract_schema}->{$table}) { my %indexes = (@{ $self->{abstract_schema}{$table}{INDEXES} }); - return dclone($indexes{$index}); + return $indexes{$index}; } return undef; } @@ -1538,23 +1579,81 @@ sub set_column { my ($self, $table, $column, $new_def) = @_; - my $abstract_fields = \@{ $self->{abstract_schema}{$table}{FIELDS} }; + my $fields = \@{ $self->{abstract_schema}{$table}{FIELDS} }; + $self->_set_object($table, $column, $new_def, $fields); +} + +sub set_index { - my $field_position = lsearch($abstract_fields, $column) + 1; - # If the column doesn't exist, then add it. - if (!$field_position) { - push(@$abstract_fields, $column); - push(@$abstract_fields, $new_def); +=item C<set_index($table, $name, $definition)> + + Description: Changes the definition of an index in this Schema object. + If the index doesn't exist, it will be added. + The table that you specify must already exist in the Schema. + NOTE: This does not affect the database on the disk. + Use the C<Bugzilla::DB> "Schema Modification Methods" + if you want to do that. + Params: $table - The table the index is on. + $name - The name of the index. + $definition - A hashref or an arrayref. An index + definition in C<ABSTRACT_SCHEMA> format. + Returns: nothing + +=cut + + my ($self, $table, $name, $definition) = @_; + + my $indexes = \@{ $self->{abstract_schema}{$table}{INDEXES} }; + $self->_set_object($table, $name, $definition, $indexes); +} + +# A private helper for set_index and set_column. +# This does the actual "work" of those two functions. +# $array_to_change is an arrayref. +sub _set_object { + my ($self, $table, $name, $definition, $array_to_change) = @_; + + my $obj_position = lsearch($array_to_change, $name) + 1; + # If the object doesn't exist, then add it. + if (!$obj_position) { + push(@$array_to_change, $name); + push(@$array_to_change, $definition); } - # We're modifying an existing column. + # We're modifying an existing object in the Schema. else { - splice(@$abstract_fields, $field_position, 1, $new_def); + splice(@$array_to_change, $obj_position, 1, $definition); } $self->{schema} = dclone($self->{abstract_schema}); $self->_adjust_schema(); } +=item C<delete_index($table, $name)> + + Description: Removes an index definition from this Schema object. + If the index doesn't exist, we will fail. + The table that you specify must exist in the Schema. + NOTE: This does not affect the database on the disk. + Use the C<Bugzilla::DB> "Schema Modification Methods" + if you want to do that. + Params: $table - The table the index is on. + $name - The name of the index that we're removing. + Returns: nothing + +=cut +sub delete_index { + my ($self, $table, $name) = @_; + + my $indexes = $self->{abstract_schema}{$table}{INDEXES}; + my $name_position = lsearch($indexes, $name); + die "Attempted to delete nonexistent index $name on the $table table" + if $name_position == -1; + # Delete the key/value pair from the array. + splice(@$indexes, $name_position, 2); + $self->{schema} = dclone($self->{abstract_schema}); + $self->_adjust_schema(); +} + sub columns_equal { =item C<columns_equal($col_one, $col_two)> diff --git a/Bugzilla/DB/Schema/Mysql.pm b/Bugzilla/DB/Schema/Mysql.pm index fa6e2d5ba..6340998b7 100644 --- a/Bugzilla/DB/Schema/Mysql.pm +++ b/Bugzilla/DB/Schema/Mysql.pm @@ -108,4 +108,9 @@ sub get_alter_column_ddl { return (("ALTER TABLE $table CHANGE COLUMN $column $column $new_ddl")); } +sub get_drop_index_ddl { + my ($self, $table, $name) = @_; + return ("DROP INDEX $name ON $table"); +} + 1; |