Commit 946aa227 authored by mkanat%kerio.com's avatar mkanat%kerio.com

Bug 286689: Cross-DB bz_add_index and bz_drop_index (Part of Bug 285111)

Patch By Max Kanat-Alexander <mkanat@kerio.com> r=Tomas.Kopal, a=justdave
parent 7ee3130c
......@@ -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
......
......@@ -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)>
......
......@@ -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;
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