]> git.ipfire.org Git - thirdparty/bugzilla.git/commitdiff
Bug 286689: Cross-DB bz_add_index and bz_drop_index (Part of Bug 285111)
authormkanat%kerio.com <>
Tue, 22 Mar 2005 16:56:52 +0000 (16:56 +0000)
committermkanat%kerio.com <>
Tue, 22 Mar 2005 16:56:52 +0000 (16:56 +0000)
Patch By Max Kanat-Alexander <mkanat@kerio.com> r=Tomas.Kopal, a=justdave

Bugzilla/DB.pm
Bugzilla/DB/Schema.pm
Bugzilla/DB/Schema/Mysql.pm

index 292925a6ff52ad4786a18d1dc7ed6aa358b4e05f..2168e6ae40256cc72e78c54d3708fa5b436e0ef4 100644 (file)
@@ -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
 
 
index 525ab99f6834abf1e3349303b721bd894d49915f..801f353d74019c5f51af3b29868a119b92ef32fc 100644 (file)
@@ -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)>
index fa6e2d5ba9c4ee70a8746eac29aa417525b89db8..6340998b789b84a378236fd62efaf8f60e748042 100644 (file)
@@ -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;