summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Bugzilla/DB.pm56
-rw-r--r--Bugzilla/DB/Schema.pm141
-rw-r--r--Bugzilla/DB/Schema/Mysql.pm5
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;