]> git.ipfire.org Git - thirdparty/bugzilla.git/commitdiff
Bug 277617: Move database-manipulation subroutines in checksetup to Bugzilla::DB...
authormkanat%kerio.com <>
Wed, 2 Mar 2005 05:19:19 +0000 (05:19 +0000)
committermkanat%kerio.com <>
Wed, 2 Mar 2005 05:19:19 +0000 (05:19 +0000)
Patch By Max Kanat-Alexander <mkanat@kerio.com> r=glob, a=justdave

Bugzilla/DB.pm
checksetup.pl

index e4aa779b83332ecb3b54374c9d3ba53c87a3021c..073e929ebaea4e456fdd2e6337300004e91339d8 100644 (file)
@@ -233,6 +233,158 @@ sub bz_get_field_defs {
     return(@fields);
 }
 
+# XXX - Need to make this cross-db compatible
+# XXX - This shouldn't print stuff to stdout
+sub bz_add_field ($$$) {
+    my ($self, $table, $field, $definition) = @_;
+
+    my $ref = $self->bz_get_field_def($table, $field);
+    return if $ref; # already added?
+
+    print "Adding new field $field to table $table ...\n";
+    $self->do("ALTER TABLE $table
+              ADD COLUMN $field $definition");
+}
+
+# XXX - Need to make this cross-db compatible
+# XXX - This shouldn't print stuff to stdout
+sub bz_change_field_type ($$$) {
+    my ($self, $table, $field, $newtype) = @_;
+
+    my $ref = $self->bz_get_field_def($table, $field);
+
+    my $oldtype = $ref->[1];
+    if (! $ref->[2]) {
+        $oldtype .= qq{ not null};
+    }
+    if ($ref->[4]) {
+        $oldtype .= qq{ default "$ref->[4]"};
+    }
+
+    if ($oldtype ne $newtype) {
+        print "Updating field type $field in table $table ...\n";
+        print "old: $oldtype\n";
+        print "new: $newtype\n";
+        $self->do("ALTER TABLE $table
+                  CHANGE $field
+                  $field $newtype");
+    }
+}
+
+# XXX - Need to make this cross-db compatible
+# XXX - This shouldn't print stuff to stdout
+sub bz_drop_field ($$) {
+    my ($self, $table, $field) = @_;
+
+    my $ref = $self->bz_get_field_def($table, $field);
+    return unless $ref; # already dropped?
+
+    print "Deleting unused field $field from table $table ...\n";
+    $self->do("ALTER TABLE $table
+              DROP COLUMN $field");
+}
+
+# XXX - Needs to be made cross-db compatible
+sub bz_drop_table_indexes ($) {
+    my ($self, $table) = @_;
+    my %seen;
+
+    # get the list of indexes
+    my $sth = $self->prepare("SHOW INDEX FROM $table");
+    $sth->execute;
+
+    # drop each index
+    while ( my $ref = $sth->fetchrow_arrayref) {
+
+      # note that some indexes are described by multiple rows in the
+      # index table, so we may have already dropped the index described
+      # in the current row.
+      next if exists $seen{$$ref[2]};
+
+      if ($$ref[2] eq 'PRIMARY') {
+          # The syntax for dropping a PRIMARY KEY is different
+          # from the normal DROP INDEX syntax.
+          $self->do("ALTER TABLE $table DROP PRIMARY KEY");
+      }
+      else {
+          $self->do("ALTER TABLE $table DROP INDEX $$ref[2]");
+      }
+      $seen{$$ref[2]} = 1;
+
+    }
+}
+
+# XXX - Needs to be made cross-db compatible
+sub bz_rename_field ($$$) {
+    my ($self, $table, $field, $newname) = @_;
+
+    my $ref = $self->bz_get_field_def($table, $field);
+    return unless $ref; # already renamed?
+
+    if ($$ref[1] ne $newname) {
+        print "Updating field $field in table $table ...\n";
+        my $type = $$ref[1];
+        $type .= " NOT NULL" if !$$ref[2];
+        $type .= " auto_increment" if $$ref[5] =~ /auto_increment/;
+        $self->do("ALTER TABLE $table
+                  CHANGE $field
+                  $newname $type");
+    }
+}
+
+# XXX - Needs to be made cross-db compatible.
+sub bz_get_field_def ($$) {
+    my ($self, $table, $field) = @_;
+    my $sth = $self->prepare("SHOW COLUMNS FROM $table");
+    $sth->execute;
+
+    while (my $ref = $sth->fetchrow_arrayref) {
+        next if $$ref[0] ne $field;
+        return $ref;
+   }
+}
+
+# XXX - Needs to be made cross-db compatible
+sub bz_get_index_count ($) {
+    my ($self, $table) = @_;
+
+    my $sth = $self->prepare("SHOW INDEX FROM $table");
+    $sth->execute;
+
+    if ( $sth->rows == -1 ) {
+      die ("Unexpected response while counting indexes in $table:" .
+           " \$sth->rows == -1");
+    }
+
+    return ($sth->rows);
+}
+
+# XXX - Needs to be made cross-db compatible.
+sub bz_get_index_def ($$) {
+    my ($self, $table, $field) = @_;
+    my $sth = $self->prepare("SHOW INDEX FROM $table");
+    $sth->execute;
+
+    while (my $ref = $sth->fetchrow_arrayref) {
+        next if $$ref[2] ne $field;
+        return $ref;
+   }
+}
+
+# XXX - Needs to be made cross-db compatible
+sub bz_table_exists ($) {
+   my ($self, $table) = @_;
+   my $exists = 0;
+   my $sth = $self->prepare("SHOW TABLES");
+   $sth->execute;
+   while (my ($dbtable) = $sth->fetchrow_array ) {
+      if ($dbtable eq $table) {
+         $exists = 1;
+      }
+   }
+   return $exists;
+}
+
 sub bz_last_key {
     my ($self, $table, $column) = @_;
 
@@ -342,8 +494,18 @@ Bugzilla::DB - Database access routines, using L<DBI>
   # Get the results
   my @result = $sth->fetchrow_array;
 
+  # Schema Changes
+  $dbh->bz_add_field($table, $column, $definition);
+  $dbh->bz_change_field_type($table, $column, $newtype);
+  $dbh->bz_drop_field($table, $column);
+  $dbh->bz_drop_table_indexes($table);
+  $dbh->bz_rename_field($table, $column, $newname);
+
   # Schema Information
-  my @fields = $dbh->bz_get_field_defs();
+  my @fields    = $dbh->bz_get_field_defs();
+  my @fieldinfo = $dbh->bz_get_field_def($table, $column);
+  my @indexinfo = $dbh->bz_get_index_def($table, $index);
+  my $exists    = $dbh->bz_table_exists($table);
 
 =head1 DESCRIPTION
 
@@ -534,6 +696,51 @@ formatted SQL command have prefix C<sql_>. All other methods have prefix C<bz_>.
               $column = name of column containing serial data type (scalar)
  Returns:     Last inserted ID (scalar)
 
+=item C<bz_add_field>
+
+ Description: Adds a new column to a table in the database. Prints out
+              a brief statement that it did so, to stdout.
+ Params:      $table = the table where the column is being added
+              $column = the name of the new column
+              $definition = SQL for defining the new column
+ Returns:     none
+
+=item C<bz_change_field_type>
+
+ Description: Changes the data type of a column in a table. Prints out 
+              the changes being made to stdout. If the new type is the 
+              same as the old type, the function returns without changing
+              anything.
+ Params:      $table = the table where the column is
+              $column = the name of the column you want to change
+              $newtype = the new data type of the column, in SQL format.
+ Returns:     none
+
+=item C<bz_drop_field>
+
+ Description: Removes a column from a database table. If the column 
+              doesn't exist, we return without doing anything. If we do
+              anything, we print a short message to stdout about the change.
+ Params:      $table = The table where the column is
+              $column = The name of the column you want to drop
+ Returns:     none
+
+=item C<bz_drop_table_indexes>
+
+ Description: Drops all indexes on a given table.
+ Params:      $table = the table on which you wish to remove all indexes
+ Returns:     none
+
+=item C<bz_rename_field>
+
+ Description: Renames a column in a database table. If the column 
+              doesn't exist, or if the new name is the same as the 
+              old name, we return without changing anything.
+ Params:      $table = the table where the column is that you want to rename
+              $column = the name of the column you want to rename
+              $newname = the new name of the column
+ Returns:     none
+
 =item C<bz_get_field_defs>
 
  Description: Returns a list of all the "bug" fields in Bugzilla. The list
@@ -541,6 +748,53 @@ formatted SQL command have prefix C<sql_>. All other methods have prefix C<bz_>.
  Params:      none
  Returns:     List of all the "bug" fields
 
+=item C<bz_get_field_def>
+
+ Description: Returns information about a column in a table in the database.
+ Params:      $table = name of table containing the column (scalar)
+              $column = column you want info about (scalar)
+ Returns:     An reference to an array containing information about the
+              field, with the following information in each array place:
+              0 = column name
+              1 = column type
+              2 = 'YES' if the column can be NULL, empty string otherwise
+              3 = The type of key, either 'MUL', 'UNI', 'PRI, or ''.
+              4 = The default value
+              5 = An "extra" column, per MySQL docs. Don't use it.
+              If the column does not exist, the function returns undef.
+
+=item C<bz_get_index_count>
+
+ Description: Returns the number of indexes on a certain table.
+ Params:      $table = the table that you want to count indexes on
+ Returns:     The number of indexes on the table.
+
+=item C<bz_get_index_def>
+
+ Description: Returns information about an index on a table in the database.
+ Params:      $table = name of table containing the index (scalar)
+              $index = name of the index (scalar)
+ Returns:     A reference to an array containing information about the
+              index, with the following information in each array place:
+              0 = name of the table that the index is on
+              1 = 0 if unique, 1 if not unique
+              2 = name of the index
+              3 = seq_in_index (either 1 or 0)
+              4 = Name of ONE column that the index is on
+              5 = 'Collation' of the index. Usually 'A'.
+              6 = Cardinality. Either a number or undef.
+              7 = sub_part. Usually undef. Sometimes 1.
+              8 = "packed". Usually undef.
+              9 = comments. Usually an empty string. Sometimes 'FULLTEXT'.
+              If the index does not exist, the function returns undef.
+
+=item C<bz_table_exists>
+
+ Description: Returns whether or not the specified table exists in the DB.
+ Params:      $table = the name of the table you're checking the existence
+                       of (scalar)
+ Returns:     A true value if the table exists, a false value otherwise.
+
 =item C<bz_start_transaction>
 
  Description: Starts a transaction if supported by the database being used
index 0aaebe652791060993dbdaf987ed632f0e7797bf..934229965bc671199ef5ab0fe544eb718353651b 100755 (executable)
@@ -2319,77 +2319,6 @@ AddFDef("content", "Content", 0);
 # Detect changed local settings
 ###########################################################################
 
-sub GetFieldDef ($$)
-{
-    my ($table, $field) = @_;
-    my $sth = $dbh->prepare("SHOW COLUMNS FROM $table");
-    $sth->execute;
-
-    while (my $ref = $sth->fetchrow_arrayref) {
-        next if $$ref[0] ne $field;
-        return $ref;
-    }
-}
-
-sub GetIndexDef ($$)
-{
-    my ($table, $field) = @_;
-    my $sth = $dbh->prepare("SHOW INDEX FROM $table");
-    $sth->execute;
-
-    while (my $ref = $sth->fetchrow_arrayref) {
-        next if $$ref[2] ne $field;
-        return $ref;
-    }
-}
-
-sub CountIndexes ($)
-{
-    my ($table) = @_;
-    
-    my $sth = $dbh->prepare("SHOW INDEX FROM $table");
-    $sth->execute;
-
-    if ( $sth->rows == -1 ) {
-      die ("Unexpected response while counting indexes in $table:" .
-           " \$sth->rows == -1");
-    }
-    
-    return ($sth->rows);
-}
-
-sub DropIndexes ($)
-{
-    my ($table) = @_;
-    my %SEEN;
-
-    # get the list of indexes
-    #
-    my $sth = $dbh->prepare("SHOW INDEX FROM $table");
-    $sth->execute;
-
-    # drop each index
-    #
-    while ( my $ref = $sth->fetchrow_arrayref) {
-      
-        # note that some indexes are described by multiple rows in the
-        # index table, so we may have already dropped the index described
-        # in the current row.
-        # 
-        next if exists $SEEN{$$ref[2]};
-
-        if ($$ref[2] eq 'PRIMARY') {
-            # The syntax for dropping a PRIMARY KEY is different
-            # from the normal DROP INDEX syntax.
-            $dbh->do("ALTER TABLE $table DROP PRIMARY KEY"); 
-        }
-        else {
-            $dbh->do("ALTER TABLE $table DROP INDEX $$ref[2]");
-        }
-        $SEEN{$$ref[2]} = 1;
-    }
-}
-
 # mkanat@kerio.com - bug 17453
 # Create the values for the tables that hold what used to be enum types.
 # Don't populate the tables if the table isn't empty.
@@ -2488,123 +2417,30 @@ unless ($sth->rows) {
 # Update the tables to the current definition
 ###########################################################################
 
-#
-# As time passes, fields in tables get deleted, added, changed and so on.
-# So we need some helper subroutines to make this possible:
-#
-
-sub ChangeFieldType ($$$)
-{
-    my ($table, $field, $newtype) = @_;
-
-    my $ref = GetFieldDef($table, $field);
-    #print "0: $$ref[0]  1: $$ref[1]  2: $$ref[2]  3: $$ref[3]  4: $$ref[4]\n";
-
-    my $oldtype = $ref->[1];
-    if (! $ref->[2]) {
-        $oldtype .= qq{ not null};
-    }
-    if ($ref->[4]) {
-        $oldtype .= qq{ default "$ref->[4]"};
-    }
-
-    if ($oldtype ne $newtype) {
-        print "Updating field type $field in table $table ...\n";
-        print "old: $oldtype\n";
-        print "new: $newtype\n";
-#        'not null' should be passed as part of the call to ChangeFieldType()
-#        $newtype .= " NOT NULL" if $$ref[3];
-        $dbh->do("ALTER TABLE $table
-                  CHANGE $field
-                  $field $newtype");
-    }
-}
-
-sub RenameField ($$$)
-{
-    my ($table, $field, $newname) = @_;
-
-    my $ref = GetFieldDef($table, $field);
-    return unless $ref; # already fixed?
-    #print "0: $$ref[0]  1: $$ref[1]  2: $$ref[2]  3: $$ref[3]  4: $$ref[4]\n";
-
-    if ($$ref[1] ne $newname) {
-        print "Updating field $field in table $table ...\n";
-        my $type = $$ref[1];
-        $type .= " NOT NULL" if !$$ref[2];
-        $type .= " auto_increment" if $$ref[5] =~ /auto_increment/;
-        $dbh->do("ALTER TABLE $table
-                  CHANGE $field
-                  $newname $type");
-    }
-}
-
-sub AddField ($$$)
-{
-    my ($table, $field, $definition) = @_;
-
-    my $ref = GetFieldDef($table, $field);
-    return if $ref; # already added?
-
-    print "Adding new field $field to table $table ...\n";
-    $dbh->do("ALTER TABLE $table
-              ADD COLUMN $field $definition");
-}
-
-sub DropField ($$)
-{
-    my ($table, $field) = @_;
-
-    my $ref = GetFieldDef($table, $field);
-    return unless $ref; # already dropped?
-
-    print "Deleting unused field $field from table $table ...\n";
-    $dbh->do("ALTER TABLE $table
-              DROP COLUMN $field");
-}
-
-# this uses a mysql specific command. 
-sub TableExists ($)
-{
-    my ($table) = @_;
-    my @tables;
-    my $dbtable;
-    my $exists = 0;
-    my $sth = $dbh->prepare("SHOW TABLES");
-    $sth->execute;
-    while ( ($dbtable) = $sth->fetchrow_array ) {
-        if ($dbtable eq $table) {
-            $exists = 1;
-        } 
-   } 
-   return $exists;
-}   
-
-
 # really old fields that were added before checksetup.pl existed
 # but aren't in very old bugzilla's (like 2.1)
 # Steve Stock (sstock@iconnect-inc.com)
 
 # bug 157756 - groupsets replaced by maps
-# AddField('bugs', 'groupset', 'bigint not null'); 
-AddField('bugs', 'target_milestone', 'varchar(20) not null default "---"');
-AddField('bugs', 'qa_contact', 'mediumint not null');
-AddField('bugs', 'status_whiteboard', 'mediumtext not null');
-AddField('products', 'disallownew', 'tinyint not null');
-AddField('products', 'milestoneurl', 'tinytext not null');
-AddField('components', 'initialqacontact', 'tinytext not null');
-AddField('components', 'description', 'mediumtext not null');
+# $dbh->bz_add_field('bugs', 'groupset', 'bigint not null'); 
+$dbh->bz_add_field('bugs', 'target_milestone', 'varchar(20) not null default "---"');
+$dbh->bz_add_field('bugs', 'qa_contact', 'mediumint not null');
+$dbh->bz_add_field('bugs', 'status_whiteboard', 'mediumtext not null');
+$dbh->bz_add_field('products', 'disallownew', 'tinyint not null');
+$dbh->bz_add_field('products', 'milestoneurl', 'tinytext not null');
+$dbh->bz_add_field('components', 'initialqacontact', 'tinytext not null');
+$dbh->bz_add_field('components', 'description', 'mediumtext not null');
 
 # 1999-06-22 Added an entry to the attachments table to record who the
 # submitter was.  Nothing uses this yet, but it still should be recorded.
 
-AddField('attachments', 'submitter_id', 'mediumint not null');
+$dbh->bz_add_field('attachments', 'submitter_id', 'mediumint not null');
 
 #
 # One could even populate this field automatically, e.g. with
 #
 # unless (GetField('attachments', 'submitter_id') {
-#    AddField ...
+#    $dbh->bz_add_field ...
 #    populate
 # }
 #
@@ -2616,7 +2452,7 @@ AddField('attachments', 'submitter_id', 'mediumint not null');
 # as a column name.  So, I have had to rename a column in the bugs_activity
 # table.
 
-RenameField ('bugs_activity', 'when', 'bug_when');
+$dbh->bz_rename_field('bugs_activity', 'when', 'bug_when');
 
 
 
@@ -2628,9 +2464,9 @@ RenameField ('bugs_activity', 'when', 'bug_when');
 # (P.S. All is not lost; it appears that the latest betas of MySQL support
 # a new table format which will allow 32 indices.)
 
-DropField('bugs', 'area');
-AddField('bugs',     'votes',        'mediumint not null, add index (votes)');
-AddField('products', 'votesperuser', 'mediumint not null');
+$dbh->bz_drop_field('bugs', 'area');
+$dbh->bz_add_field('bugs',     'votes',        'mediumint not null, add index (votes)');
+$dbh->bz_add_field('products', 'votesperuser', 'mediumint not null');
 
 
 
@@ -2646,11 +2482,11 @@ AddField('products', 'votesperuser', 'mediumint not null');
 
 # Only do this if these fields still exist - they're removed below, in
 # a later change
-if (GetFieldDef('products', 'product')) {
-    ChangeFieldType ('bugs',       'product', 'varchar(64) not null');
-    ChangeFieldType ('components', 'program', 'varchar(64)');
-    ChangeFieldType ('products',   'product', 'varchar(64)');
-    ChangeFieldType ('versions',   'program', 'varchar(64) not null');
+if ($dbh->bz_get_field_def('products', 'product')) {
+    $dbh->bz_change_field_type('bugs',       'product', 'varchar(64) not null');
+    $dbh->bz_change_field_type('components', 'program', 'varchar(64)');
+    $dbh->bz_change_field_type('products',   'product', 'varchar(64)');
+    $dbh->bz_change_field_type('versions',   'program', 'varchar(64) not null');
 }
 
 # 2000-01-16 Added a "keywords" field to the bugs table, which
@@ -2658,8 +2494,8 @@ if (GetFieldDef('products', 'product')) {
 # bug.  This is so that I can easily sort and display a keywords
 # column in bug lists.
 
-if (!GetFieldDef('bugs', 'keywords')) {
-    AddField('bugs', 'keywords', 'mediumtext not null');
+if (!$dbh->bz_get_field_def('bugs', 'keywords')) {
+    $dbh->bz_add_field('bugs', 'keywords', 'mediumtext not null');
 
     my @kwords;
     print "Making sure 'keywords' field of table 'bugs' is empty ...\n";
@@ -2697,7 +2533,7 @@ if (!GetFieldDef('bugs', 'keywords')) {
 # empty, then this account has been disabled, and this field is to contain
 # text describing why.
 
-AddField('profiles', 'disabledtext',  'mediumtext not null');
+$dbh->bz_add_field('profiles', 'disabledtext',  'mediumtext not null');
 
 
 
@@ -2718,7 +2554,7 @@ sub WriteOneDesc {
 }
 
 
-if (GetFieldDef('bugs', 'long_desc')) {
+if ($dbh->bz_get_field_def('bugs', 'long_desc')) {
     eval("use Date::Parse");
     eval("use Date::Format");
     my $sth = $dbh->prepare("SELECT count(*) FROM bugs");
@@ -2827,7 +2663,7 @@ if (GetFieldDef('bugs', 'long_desc')) {
 
     print "\n\n";
 
-    DropField('bugs', 'long_desc');
+    $dbh->bz_drop_field('bugs', 'long_desc');
 
     $dbh->bz_unlock_tables();
 }
@@ -2837,8 +2673,8 @@ if (GetFieldDef('bugs', 'long_desc')) {
 # different fields we keep an activity log on.  The bugs_activity table
 # now has a pointer into that table instead of recording the name directly.
 
-if (GetFieldDef('bugs_activity', 'field')) {
-    AddField('bugs_activity', 'fieldid',
+if ($dbh->bz_get_field_def('bugs_activity', 'field')) {
+    $dbh->bz_add_field('bugs_activity', 'fieldid',
              'mediumint not null, ADD INDEX (fieldid)');
     print "Populating new fieldid field ...\n";
 
@@ -2862,7 +2698,7 @@ if (GetFieldDef('bugs_activity', 'field')) {
     }
     $dbh->bz_unlock_tables();
 
-    DropField('bugs_activity', 'field');
+    $dbh->bz_drop_field('bugs_activity', 'field');
 }
 
         
@@ -2874,8 +2710,8 @@ if (GetFieldDef('bugs_activity', 'field')) {
 # 2001-04-29 jake@bugzilla.org - The newemailtech field is no longer needed
 #   http://bugzilla.mozilla.org/show_bugs.cgi?id=71552
 
-if (!GetFieldDef('bugs', 'lastdiffed')) {
-    AddField('bugs', 'lastdiffed', 'datetime not null');
+if (!$dbh->bz_get_field_def('bugs', 'lastdiffed')) {
+    $dbh->bz_add_field('bugs', 'lastdiffed', 'datetime not null');
     $dbh->do('UPDATE bugs SET lastdiffed = now(), delta_ts = delta_ts');
 }
 
@@ -2885,7 +2721,7 @@ if (!GetFieldDef('bugs', 'lastdiffed')) {
 # in my database.  This code detects that, cleans up the duplicates, and
 # then tweaks the table to declare the field to be unique.  What a pain.
 
-if (GetIndexDef('profiles', 'login_name')->[1]) {
+if ($dbh->bz_get_index_def('profiles', 'login_name')->[1]) {
     print "Searching for duplicate entries in the profiles table ...\n";
     while (1) {
         # This code is weird in that it loops around and keeps doing this
@@ -2934,11 +2770,11 @@ if (GetIndexDef('profiles', 'login_name')->[1]) {
 # bugs" link appears at the bottom of each page.  Also can control
 # whether each named query should show up there.
 
-AddField('profiles', 'mybugslink', 'tinyint not null default 1');
-AddField('namedqueries', 'linkinfooter', 'tinyint not null');
+$dbh->bz_add_field('profiles', 'mybugslink', 'tinyint not null default 1');
+$dbh->bz_add_field('namedqueries', 'linkinfooter', 'tinyint not null');
 
 
-if (($_ = GetFieldDef('components', 'initialowner')) and 
+if (($_ = $dbh->bz_get_field_def('components', 'initialowner')) and 
     ($_->[1] eq 'tinytext')) {
     $sth = $dbh->prepare(
          "SELECT program, value, initialowner, initialqacontact " .
@@ -2974,10 +2810,10 @@ if (($_ = GetFieldDef('components', 'initialowner')) and
         $s3->execute();
     }
 
-    ChangeFieldType('components','initialowner','mediumint');
+    $dbh->bz_change_field_type('components','initialowner','mediumint');
 }
 
-if (($_ = GetFieldDef('components', 'initialqacontact')) and 
+if (($_ = $dbh->bz_get_field_def('components', 'initialqacontact')) and 
     ($_->[1] eq 'tinytext')) {
     $sth = $dbh->prepare(
            "SELECT program, value, initialqacontact, initialqacontact " .
@@ -3012,18 +2848,18 @@ if (($_ = GetFieldDef('components', 'initialqacontact')) and
         $s3->execute();
     }
 
-    ChangeFieldType('components','initialqacontact','mediumint');
+    $dbh->bz_change_field_type('components','initialqacontact','mediumint');
 }
 
 
-if (!GetFieldDef('bugs', 'everconfirmed')) {
-    AddField('bugs', 'everconfirmed',  'tinyint not null');
+if (!$dbh->bz_get_field_def('bugs', 'everconfirmed')) {
+    $dbh->bz_add_field('bugs', 'everconfirmed',  'tinyint not null');
     $dbh->do("UPDATE bugs SET everconfirmed = 1, delta_ts = delta_ts");
 }
-AddField('products', 'maxvotesperbug', 'smallint not null default 10000');
-AddField('products', 'votestoconfirm', 'smallint not null');
+$dbh->bz_add_field('products', 'maxvotesperbug', 'smallint not null default 10000');
+$dbh->bz_add_field('products', 'votestoconfirm', 'smallint not null');
 # bug 157756 - groupsets replaced by maps
-# AddField('profiles', 'blessgroupset', 'bigint not null');
+# $dbh->bz_add_field('profiles', 'blessgroupset', 'bigint not null');
 
 # 2000-03-21 Adding a table for target milestones to 
 # database - matthew@zeroknowledge.com
@@ -3073,16 +2909,16 @@ if (!($sth->fetchrow_arrayref()->[0])) {
 # doing), and made the size of the value field in the milestones table match
 # the size of the target_milestone field in the bugs table.
 
-ChangeFieldType('bugs', 'target_milestone',
+$dbh->bz_change_field_type('bugs', 'target_milestone',
                 'varchar(20) not null default "---"');
-ChangeFieldType('milestones', 'value', 'varchar(20) not null');
+$dbh->bz_change_field_type('milestones', 'value', 'varchar(20) not null');
 
 
 # 2000-03-23 Added a defaultmilestone field to the products table, so that
 # we know which milestone to initially assign bugs to.
 
-if (!GetFieldDef('products', 'defaultmilestone')) {
-    AddField('products', 'defaultmilestone',
+if (!$dbh->bz_get_field_def('products', 'defaultmilestone')) {
+    $dbh->bz_add_field('products', 'defaultmilestone',
              'varchar(20) not null default "---"');
     $sth = $dbh->prepare("SELECT product, defaultmilestone FROM products");
     $sth->execute();
@@ -3104,22 +2940,22 @@ if (!GetFieldDef('products', 'defaultmilestone')) {
 # prevents certain database inconsistencies, and, moreover, is required for
 # new generalized list code to work.
 
-if ( CountIndexes('cc') != 3 ) {
+if ( $dbh->bz_get_index_count('cc') != 3 ) {
 
     # XXX should eliminate duplicate entries before altering
     #
     print "Recreating indexes on cc table.\n";
-    DropIndexes('cc');
+    $dbh->bz_drop_table_indexes('cc');
     $dbh->do("ALTER TABLE cc ADD UNIQUE (bug_id,who)");
     $dbh->do("ALTER TABLE cc ADD INDEX (who)");
 }    
 
-if ( CountIndexes('keywords') != 3 ) {
+if ( $dbh->bz_get_index_count('keywords') != 3 ) {
 
     # XXX should eliminate duplicate entries before altering
     #
     print "Recreating indexes on keywords table.\n";
-    DropIndexes('keywords');
+    $dbh->bz_drop_table_indexes('keywords');
     $dbh->do("ALTER TABLE keywords ADD INDEX (keywordid)");
     $dbh->do("ALTER TABLE keywords ADD UNIQUE (bug_id,keywordid)");
 
@@ -3164,18 +3000,18 @@ if (!($sth->fetchrow_arrayref()->[0])) {
 
 # 2000-12-18.  Added an 'emailflags' field for storing preferences about
 # when email gets sent on a per-user basis.
-if (!GetFieldDef('profiles', 'emailflags')) {
-    AddField('profiles', 'emailflags', 'mediumtext');
+if (!$dbh->bz_get_field_def('profiles', 'emailflags')) {
+    $dbh->bz_add_field('profiles', 'emailflags', 'mediumtext');
 }
 
 # 2000-11-27 For Bugzilla 2.5 and later. Change table 'comments' to 
 # 'longdescs' - the new name of the comments table.
-if (&TableExists('comments')) {
-    RenameField ('comments', 'when', 'bug_when');
-    ChangeFieldType('comments', 'bug_id', 'mediumint not null');
-    ChangeFieldType('comments', 'who', 'mediumint not null');
-    ChangeFieldType('comments', 'bug_when', 'datetime not null');
-    RenameField('comments','comment','thetext');
+if ($dbh->bz_table_exists('comments')) {
+    $dbh->bz_rename_field('comments', 'when', 'bug_when');
+    $dbh->bz_change_field_type('comments', 'bug_id', 'mediumint not null');
+    $dbh->bz_change_field_type('comments', 'who', 'mediumint not null');
+    $dbh->bz_change_field_type('comments', 'bug_when', 'datetime not null');
+    $dbh->bz_rename_field('comments','comment','thetext');
     # Here we rename comments to longdescs
     $dbh->do("DROP TABLE longdescs");
     $dbh->do("ALTER TABLE comments RENAME longdescs");
@@ -3198,13 +3034,13 @@ unless (-d "$datadir/duplicates") {
 # without enabling them to extend the life of the group by adding bugs to it.
 # http://bugzilla.mozilla.org/show_bug.cgi?id=75482
 #
-AddField('groups', 'isactive', 'tinyint not null default 1');
+$dbh->bz_add_field('groups', 'isactive', 'tinyint not null default 1');
 
 #
 # 2001-06-15 myk@mozilla.org:
 # isobsolete determines whether or not an attachment is pertinent/relevant/valid.
 #
-AddField('attachments', 'isobsolete', 'tinyint not null default 0');
+$dbh->bz_add_field('attachments', 'isobsolete', 'tinyint not null default 0');
 
 # 2001-04-29 jake@bugzilla.org - Remove oldemailtech
 #   http://bugzilla.mozilla.org/show_bugs.cgi?id=71552
@@ -3214,19 +3050,19 @@ if (-d 'shadow') {
     unlink glob("shadow/.*");
     rmdir "shadow";
 }
-DropField("profiles", "emailnotification");
-DropField("profiles", "newemailtech");
+$dbh->bz_drop_field("profiles", "emailnotification");
+$dbh->bz_drop_field("profiles", "newemailtech");
 
 
 # 2003-11-19; chicks@chicks.net; bug 225973: fix field size to accomodate
 # wider algorithms such as Blowfish. Note that this needs to be run
 # before recrypting passwords in the following block.
-ChangeFieldType('profiles', 'cryptpassword', 'varchar(128)');
+$dbh->bz_change_field_type('profiles', 'cryptpassword', 'varchar(128)');
 
 # 2001-06-12; myk@mozilla.org; bugs 74032, 77473:
 # Recrypt passwords using Perl &crypt instead of the mysql equivalent
 # and delete plaintext passwords from the database.
-if ( GetFieldDef('profiles', 'password') ) {
+if ( $dbh->bz_get_field_def('profiles', 'password') ) {
     
     print <<ENDTEXT;
 Your current installation of Bugzilla stores passwords in plaintext 
@@ -3256,7 +3092,7 @@ ENDTEXT
     print "$i... Done.\n";
 
     # Drop the plaintext password field.
-    DropField('profiles', 'password');
+    $dbh->bz_drop_field('profiles', 'password');
 }
 
 #
@@ -3264,20 +3100,20 @@ ENDTEXT
 # There was no index on the 'who' column in the long descriptions table.
 # This caused queries by who posted comments to take a LONG time.
 #   http://bugzilla.mozilla.org/show_bug.cgi?id=57350
-if (!defined GetIndexDef('longdescs','who')) {
+if (!defined $dbh->bz_get_index_def('longdescs','who')) {
     print "Adding index for who column in longdescs table...\n";
     $dbh->do('ALTER TABLE longdescs ADD INDEX (who)');
 }
 
 # 2001-06-15 kiko@async.com.br - Change bug:version size to avoid
 # truncates re http://bugzilla.mozilla.org/show_bug.cgi?id=9352
-ChangeFieldType('bugs', 'version','varchar(64) not null');
+$dbh->bz_change_field_type('bugs', 'version','varchar(64) not null');
 
 # 2001-07-20 jake@bugzilla.org - Change bugs_activity to only record changes
 #  http://bugzilla.mozilla.org/show_bug.cgi?id=55161
-if (GetFieldDef('bugs_activity', 'oldvalue')) {
-    AddField("bugs_activity", "removed", "tinytext");
-    AddField("bugs_activity", "added", "tinytext");
+if ($dbh->bz_get_field_def('bugs_activity', 'oldvalue')) {
+    $dbh->bz_add_field("bugs_activity", "removed", "tinytext");
+    $dbh->bz_add_field("bugs_activity", "added", "tinytext");
 
     # Need to get fieldid's for the fields that have multiple values
     my @multi = ();
@@ -3346,31 +3182,31 @@ if (GetFieldDef('bugs_activity', 'oldvalue')) {
                    AND bug_when = '$bug_when' AND fieldid = $fieldid");
     }
     print ". Done.\n";
-    DropField("bugs_activity", "oldvalue");
-    DropField("bugs_activity", "newvalue");
+    $dbh->bz_drop_field("bugs_activity", "oldvalue");
+    $dbh->bz_drop_field("bugs_activity", "newvalue");
 } 
 
 # 2001-07-24 jake@bugzilla.org - disabledtext was being handled inconsistently
 # http://bugzilla.mozilla.org/show_bug.cgi?id=90933
-ChangeFieldType("profiles", "disabledtext", "mediumtext not null");
+$dbh->bz_change_field_type("profiles", "disabledtext", "mediumtext not null");
 
 # 2001-07-26 myk@mozilla.org            bug 39816 (original)
 # 2002-02-06 bbaetz@student.usyd.edu.au bug 97471 (revision)
 # Add fields to the bugs table that record whether or not the reporter
 # and users on the cc: list can see bugs even when
 # they are not members of groups to which the bugs are restricted.
-AddField("bugs", "reporter_accessible", "tinyint not null default 1");
-AddField("bugs", "cclist_accessible", "tinyint not null default 1");
+$dbh->bz_add_field("bugs", "reporter_accessible", "tinyint not null default 1");
+$dbh->bz_add_field("bugs", "cclist_accessible", "tinyint not null default 1");
 
 # 2001-08-21 myk@mozilla.org bug84338:
 # Add a field to the bugs_activity table for the attachment ID, so installations
 # using the attachment manager can record changes to attachments.
-AddField("bugs_activity", "attach_id", "mediumint null");
+$dbh->bz_add_field("bugs_activity", "attach_id", "mediumint null");
 
 # 2002-02-04 bbaetz@student.usyd.edu.au bug 95732
 # Remove logincookies.cryptpassword, and delete entries which become
 # invalid
-if (GetFieldDef("logincookies", "cryptpassword")) {
+if ($dbh->bz_get_field_def("logincookies", "cryptpassword")) {
     # We need to delete any cookies which are invalid before dropping the
     # column
 
@@ -3387,50 +3223,50 @@ if (GetFieldDef("logincookies", "cryptpassword")) {
         $dbh->do("DELETE FROM logincookies WHERE cookie = $cookie");
     }
 
-    DropField("logincookies", "cryptpassword");
+    $dbh->bz_drop_field("logincookies", "cryptpassword");
 }
 
 # 2002-02-13 bbaetz@student.usyd.edu.au - bug 97471
 # qacontact/assignee should always be able to see bugs,
 # so remove their restriction column
-if (GetFieldDef("bugs","qacontact_accessible")) {
+if ($dbh->bz_get_field_def("bugs","qacontact_accessible")) {
     print "Removing restrictions on bugs for assignee and qacontact...\n";
 
-    DropField("bugs", "qacontact_accessible");
-    DropField("bugs", "assignee_accessible");
+    $dbh->bz_drop_field("bugs", "qacontact_accessible");
+    $dbh->bz_drop_field("bugs", "assignee_accessible");
 }
 
 # 2002-02-20 jeff.hedlund@matrixsi.com - bug 24789 time tracking
-AddField("longdescs", "work_time", "decimal(5,2) not null default 0");
-AddField("bugs", "estimated_time", "decimal(5,2) not null default 0");
-AddField("bugs", "remaining_time", "decimal(5,2) not null default 0");
-AddField("bugs", "deadline", "datetime");
+$dbh->bz_add_field("longdescs", "work_time", "decimal(5,2) not null default 0");
+$dbh->bz_add_field("bugs", "estimated_time", "decimal(5,2) not null default 0");
+$dbh->bz_add_field("bugs", "remaining_time", "decimal(5,2) not null default 0");
+$dbh->bz_add_field("bugs", "deadline", "datetime");
 
 # 2002-03-15 bbaetz@student.usyd.edu.au - bug 129466
 # 2002-05-13 preed@sigkill.com - bug 129446 patch backported to the 
 #  BUGZILLA-2_14_1-BRANCH as a security blocker for the 2.14.2 release
 # 
 # Use the ip, not the hostname, in the logincookies table
-if (GetFieldDef("logincookies", "hostname")) {
+if ($dbh->bz_get_field_def("logincookies", "hostname")) {
     # We've changed what we match against, so all entries are now invalid
     $dbh->do("DELETE FROM logincookies");
 
     # Now update the logincookies schema
-    DropField("logincookies", "hostname");
-    AddField("logincookies", "ipaddr", "varchar(40) NOT NULL");
+    $dbh->bz_drop_field("logincookies", "hostname");
+    $dbh->bz_add_field("logincookies", "ipaddr", "varchar(40) NOT NULL");
 }
 
 # 2002-08-19 - bugreport@peshkin.net bug 143826
 # Add private comments and private attachments on less-private bugs
-AddField('longdescs', 'isprivate', 'tinyint not null default 0');
-AddField('attachments', 'isprivate', 'tinyint not null default 0');
+$dbh->bz_add_field('longdescs', 'isprivate', 'tinyint not null default 0');
+$dbh->bz_add_field('attachments', 'isprivate', 'tinyint not null default 0');
 
 
 # 2002-07-03 myk@mozilla.org bug99203:
 # Add a bug alias field to the bugs table so bugs can be referenced by alias
 # in addition to ID.
-if (!GetFieldDef("bugs", "alias")) {
-    AddField("bugs", "alias", "VARCHAR(20)");
+if (!$dbh->bz_get_field_def("bugs", "alias")) {
+    $dbh->bz_add_field("bugs", "alias", "VARCHAR(20)");
     $dbh->do("ALTER TABLE bugs ADD UNIQUE (alias)");
 }
 
@@ -3455,13 +3291,13 @@ if (-r "$datadir/comments" && -s "$datadir/comments"
 
 # 2002-07-31 bbaetz@student.usyd.edu.au bug 158236
 # Remove unused column
-if (GetFieldDef("namedqueries", "watchfordiffs")) {
-    DropField("namedqueries", "watchfordiffs");
+if ($dbh->bz_get_field_def("namedqueries", "watchfordiffs")) {
+    $dbh->bz_drop_field("namedqueries", "watchfordiffs");
 }
 
 # 2002-08-12 jake@bugzilla.org/bbaetz@student.usyd.edu.au - bug 43600
 # Use integer IDs for products and components.
-if (GetFieldDef("products", "product")) {
+if ($dbh->bz_get_field_def("products", "product")) {
     print "Updating database to use product IDs.\n";
 
     # First, we need to remove possible NULL entries
@@ -3470,18 +3306,18 @@ if (GetFieldDef("products", "product")) {
     $dbh->do("DELETE FROM products WHERE product IS NULL");
     $dbh->do("DELETE FROM components WHERE value IS NULL");
 
-    AddField("products", "id", "smallint not null auto_increment primary key");
-    AddField("components", "product_id", "smallint not null");
-    AddField("versions", "product_id", "smallint not null");
-    AddField("milestones", "product_id", "smallint not null");
-    AddField("bugs", "product_id", "smallint not null");
+    $dbh->bz_add_field("products", "id", "smallint not null auto_increment primary key");
+    $dbh->bz_add_field("components", "product_id", "smallint not null");
+    $dbh->bz_add_field("versions", "product_id", "smallint not null");
+    $dbh->bz_add_field("milestones", "product_id", "smallint not null");
+    $dbh->bz_add_field("bugs", "product_id", "smallint not null");
     # The attachstatusdefs table was added in version 2.15, but removed again
     # in early 2.17.  If it exists now, we still need to perform this change
     # with product_id because the code further down which converts the
     # attachment statuses to flags depends on it.  But we need to avoid this
     # if the user is upgrading from 2.14 or earlier (because it won't be
     # there to convert).
-    AddField("attachstatusdefs", "product_id", "smallint not null") if TableExists("attachstatusdefs");
+    $dbh->bz_add_field("attachstatusdefs", "product_id", "smallint not null") if $dbh->bz_table_exists("attachstatusdefs");
     my %products;
     my $sth = $dbh->prepare("SELECT id, product FROM products");
     $sth->execute;
@@ -3501,12 +3337,12 @@ if (GetFieldDef("products", "product")) {
         $dbh->do("UPDATE bugs SET product_id = $product_id, delta_ts=delta_ts " .
                  "WHERE product = " . $dbh->quote($product));
         $dbh->do("UPDATE attachstatusdefs SET product_id = $product_id " .
-                 "WHERE product = " . $dbh->quote($product)) if TableExists("attachstatusdefs");
+                 "WHERE product = " . $dbh->quote($product)) if $dbh->bz_table_exists("attachstatusdefs");
     }
 
     print "Updating the database to use component IDs.\n";
-    AddField("components", "id", "smallint not null auto_increment primary key");
-    AddField("bugs", "component_id", "smallint not null");
+    $dbh->bz_add_field("components", "id", "smallint not null auto_increment primary key");
+    $dbh->bz_add_field("bugs", "component_id", "smallint not null");
     my %components;
     $sth = $dbh->prepare("SELECT id, value, product_id FROM components");
     $sth->execute;
@@ -3527,7 +3363,7 @@ if (GetFieldDef("products", "product")) {
     }
     print "Fixing Indexes and Uniqueness.\n";
     # Drop any indexes that may exist on the milestones table.
-    DropIndexes('milestones');
+    $dbh->bz_drop_table_indexes('milestones');
 
     $dbh->do("ALTER TABLE milestones ADD UNIQUE (product_id, value)");
     $dbh->do("ALTER TABLE bugs DROP INDEX product");
@@ -3536,16 +3372,16 @@ if (GetFieldDef("products", "product")) {
     $dbh->do("ALTER TABLE bugs ADD INDEX (component_id)");
 
     print "Removing, renaming, and retyping old product and component fields.\n";
-    DropField("components", "program");
-    DropField("versions", "program");
-    DropField("milestones", "product");
-    DropField("bugs", "product");
-    DropField("bugs", "component");
-    DropField("attachstatusdefs", "product") if TableExists("attachstatusdefs");
-    RenameField("products", "product", "name");
-    ChangeFieldType("products", "name", "varchar(64) not null");
-    RenameField("components", "value", "name");
-    ChangeFieldType("components", "name", "varchar(64) not null");
+    $dbh->bz_drop_field("components", "program");
+    $dbh->bz_drop_field("versions", "program");
+    $dbh->bz_drop_field("milestones", "product");
+    $dbh->bz_drop_field("bugs", "product");
+    $dbh->bz_drop_field("bugs", "component");
+    $dbh->bz_drop_field("attachstatusdefs", "product") if $dbh->bz_table_exists("attachstatusdefs");
+    $dbh->bz_rename_field("products", "product", "name");
+    $dbh->bz_change_field_type("products", "name", "varchar(64) not null");
+    $dbh->bz_rename_field("components", "value", "name");
+    $dbh->bz_change_field_type("components", "name", "varchar(64) not null");
 
     print "Adding indexes for products and components tables.\n";
     $dbh->do("ALTER TABLE products ADD UNIQUE (name)");
@@ -3556,7 +3392,7 @@ if (GetFieldDef("products", "product")) {
 # 2002-08-14 - bbaetz@student.usyd.edu.au - bug 153578
 # attachments creation time needs to be a datetime, not a timestamp
 my $fielddef;
-if (($fielddef = GetFieldDef("attachments", "creation_ts")) &&
+if (($fielddef = $dbh->bz_get_field_def("attachments", "creation_ts")) &&
     $fielddef->[1] =~ /^timestamp/) {
     print "Fixing creation time on attachments...\n";
 
@@ -3597,7 +3433,7 @@ if (($fielddef = GetFieldDef("attachments", "creation_ts")) &&
     }
     print "Done - converted $i attachments\n";
 
-    ChangeFieldType("attachments", "creation_ts", "datetime NOT NULL");
+    $dbh->bz_change_field_type("attachments", "creation_ts", "datetime NOT NULL");
 }
 
 # 2002-09-22 - bugreport@peshkin.net - bug 157756
@@ -3640,16 +3476,16 @@ sub ListBits {
 
 my @admins = ();
 # The groups system needs to be converted if groupset exists
-if (GetFieldDef("profiles", "groupset")) {
-    AddField('groups', 'last_changed', 'datetime not null');
+if ($dbh->bz_get_field_def("profiles", "groupset")) {
+    $dbh->bz_add_field('groups', 'last_changed', 'datetime not null');
     # Some mysql versions will promote any unique key to primary key
     # so all unique keys are removed first and then added back in
-    $dbh->do("ALTER TABLE groups DROP INDEX bit") if GetIndexDef("groups","bit");
-    $dbh->do("ALTER TABLE groups DROP INDEX name") if GetIndexDef("groups","name");
+    $dbh->do("ALTER TABLE groups DROP INDEX bit") if $dbh->bz_get_index_def("groups","bit");
+    $dbh->do("ALTER TABLE groups DROP INDEX name") if $dbh->bz_get_index_def("groups","name");
     $dbh->do("ALTER TABLE groups DROP PRIMARY KEY"); 
-    AddField('groups', 'id', 'mediumint not null auto_increment primary key');
+    $dbh->bz_add_field('groups', 'id', 'mediumint not null auto_increment primary key');
     $dbh->do("ALTER TABLE groups ADD UNIQUE (name)");
-    AddField('profiles', 'refreshed_when', 'datetime not null');
+    $dbh->bz_add_field('profiles', 'refreshed_when', 'datetime not null');
 
     # Convert all existing groupset records to map entries before removing
     # groupset fields or removing "bit" from groups.
@@ -3833,16 +3669,16 @@ if (GetFieldDef("profiles", "groupset")) {
             if (!$iscomplete);
         push @admins, $userid;
     }
-    DropField('profiles','groupset');
-    DropField('profiles','blessgroupset');
-    DropField('bugs','groupset');
-    DropField('groups','bit');
+    $dbh->bz_drop_field('profiles','groupset');
+    $dbh->bz_drop_field('profiles','blessgroupset');
+    $dbh->bz_drop_field('bugs','groupset');
+    $dbh->bz_drop_field('groups','bit');
     $dbh->do("DELETE FROM fielddefs WHERE name = " . $dbh->quote('groupset'));
 }
 
 # September 2002 myk@mozilla.org bug 98801
 # Convert the attachment statuses tables into flags tables.
-if (TableExists("attachstatuses") && TableExists("attachstatusdefs")) {
+if ($dbh->bz_table_exists("attachstatuses") && $dbh->bz_table_exists("attachstatusdefs")) {
     print "Converting attachment statuses to flags...\n";
     
     # Get IDs for the old attachment status and new flag fields.
@@ -3970,7 +3806,7 @@ if (TableExists("attachstatuses") && TableExists("attachstatusdefs")) {
 
 # 2004-12-13 Nick.Barnes@pobox.com bug 262268
 # Check for spaces and commas in flag type names; if found, rename them.
-if (TableExists("flagtypes")) {
+if ($dbh->bz_table_exists("flagtypes")) {
     # Get all names and IDs, to find broken ones and to
     # check for collisions when renaming.
     $sth = $dbh->prepare("SELECT name, id FROM flagtypes");
@@ -4065,18 +3901,18 @@ if ($mapcnt == 0) {
 
 # 2004-07-17 GRM - Remove "subscriptions" concept from charting, and add
 # group-based security instead. 
-if (TableExists("user_series_map")) {
+if ($dbh->bz_table_exists("user_series_map")) {
     # Oracle doesn't like "date" as a column name, and apparently some DBs
     # don't like 'value' either. We use the changes to subscriptions as 
     # something to hang these renamings off.
-    RenameField('series_data', 'date', 'series_date');
-    RenameField('series_data', 'value', 'series_value');
+    $dbh->bz_rename_field('series_data', 'date', 'series_date');
+    $dbh->bz_rename_field('series_data', 'value', 'series_value');
     
     # series_categories.category_id produces a too-long column name for the
     # auto-incrementing sequence (Oracle again).
-    RenameField('series_categories', 'category_id', 'id');
+    $dbh->bz_rename_field('series_categories', 'category_id', 'id');
     
-    AddField("series", "public", "tinyint(1) not null default 0");
+    $dbh->bz_add_field("series", "public", "tinyint(1) not null default 0");
 
     # Migrate public-ness across from user_series_map to new field
     $sth = $dbh->prepare("SELECT series_id from user_series_map " .
@@ -4247,15 +4083,15 @@ if (!$series_exists) {
 AddFDef("owner_idle_time", "Time Since Owner Touched", 0);
 
 # 2004-04-12 - Keep regexp-based group permissions up-to-date - Bug 240325
-if (GetFieldDef("user_group_map", "isderived")) {
-    AddField('user_group_map', 'grant_type', 'tinyint not null default 0');
+if ($dbh->bz_get_field_def("user_group_map", "isderived")) {
+    $dbh->bz_add_field('user_group_map', 'grant_type', 'tinyint not null default 0');
     $dbh->do("UPDATE user_group_map SET grant_type = " .
                              "IF(isderived, " . GRANT_DERIVED . ", " .
                              GRANT_DIRECT . ")");
     $dbh->do("DELETE FROM user_group_map 
               WHERE isbless = 0 AND grant_type != " . GRANT_DIRECT);
-    DropField("user_group_map", "isderived");
-    DropIndexes("user_group_map");
+    $dbh->bz_drop_field("user_group_map", "isderived");
+    $dbh->bz_drop_table_indexes("user_group_map");
     $dbh->do("ALTER TABLE user_group_map 
               ADD UNIQUE (user_id, group_id, grant_type, isbless)");
     # Evaluate regexp-based group memberships
@@ -4277,38 +4113,38 @@ if (GetFieldDef("user_group_map", "isderived")) {
 # 2004-07-03 - Make it possible to disable flags without deleting them
 # from the database. Bug 223878, jouni@heikniemi.net
 
-AddField('flags', 'is_active', 'tinyint not null default 1');
+$dbh->bz_add_field('flags', 'is_active', 'tinyint not null default 1');
 
 # 2004-07-16 - Make it possible to have group-group relationships other than
 # membership and bless.
-if (GetFieldDef("group_group_map", "isbless")) {
-    AddField('group_group_map', 'grant_type', 'tinyint not null default 0');
+if ($dbh->bz_get_field_def("group_group_map", "isbless")) {
+    $dbh->bz_add_field('group_group_map', 'grant_type', 'tinyint not null default 0');
     $dbh->do("UPDATE group_group_map SET grant_type = " .
                              "IF(isbless, " . GROUP_BLESS . ", " .
                              GROUP_MEMBERSHIP . ")");
-    DropIndexes("group_group_map");
-    DropField("group_group_map", "isbless");
+    $dbh->bz_drop_table_indexes("group_group_map");
+    $dbh->bz_drop_field("group_group_map", "isbless");
     $dbh->do("ALTER TABLE group_group_map 
               ADD UNIQUE (member_id, grantor_id, grant_type)");
 }    
 
 # Allow profiles to optionally be linked to a unique identifier in an outside
 # login data source
-AddField("profiles", "extern_id", "varchar(64)");
+$dbh->bz_add_field("profiles", "extern_id", "varchar(64)");
 
 # 2004-11-20 - LpSolit@netscape.net - Bug 180879
 # Add grant and request groups for flags
-AddField('flagtypes', 'grant_group_id', 'mediumint null');
-AddField('flagtypes', 'request_group_id', 'mediumint null');
+$dbh->bz_add_field('flagtypes', 'grant_group_id', 'mediumint null');
+$dbh->bz_add_field('flagtypes', 'request_group_id', 'mediumint null');
 
 # 2004-01-03 - bug 253721 erik@dasbistro.com
 # mailto is no longer just userids
-RenameField('whine_schedules', 'mailto_userid', 'mailto');
-AddField('whine_schedules', 'mailto_type', 'smallint not null default 0');
+$dbh->bz_rename_field('whine_schedules', 'mailto_userid', 'mailto');
+$dbh->bz_add_field('whine_schedules', 'mailto_type', 'smallint not null default 0');
 
 # 2005-01-29 - mkanat@kerio.com
-if (!GetFieldDef('longdescs', 'already_wrapped')) {
-    AddField('longdescs', 'already_wrapped', 'tinyint not null default 0');
+if (!$dbh->bz_get_field_def('longdescs', 'already_wrapped')) {
+    $dbh->bz_add_field('longdescs', 'already_wrapped', 'tinyint not null default 0');
     # Old, pre-wrapped comments should not be auto-wrapped
     $dbh->do('UPDATE longdescs SET already_wrapped = 1');
     # If an old comment doesn't have a newline in the first 80 characters,
@@ -4325,19 +4161,19 @@ if (!GetFieldDef('longdescs', 'already_wrapped')) {
 # 2001-09-03 (landed 2005-02-24)  dkl@redhat.com bug 17453
 # Moved enum types to separate tables so we need change the old enum types to 
 # standard varchars in the bugs table.
-ChangeFieldType ('bugs', 'bug_status', 'varchar(64) not null');
-ChangeFieldType ('bugs', 'resolution', 'varchar(64) not null');
-ChangeFieldType ('bugs', 'priority', 'varchar(64) not null');
-ChangeFieldType ('bugs', 'bug_severity', 'varchar(64) not null');
-ChangeFieldType ('bugs', 'rep_platform', 'varchar(64) not null');
-ChangeFieldType ('bugs', 'op_sys', 'varchar(64) not null');
+$dbh->bz_change_field_type('bugs', 'bug_status', 'varchar(64) not null');
+$dbh->bz_change_field_type('bugs', 'resolution', 'varchar(64) not null');
+$dbh->bz_change_field_type('bugs', 'priority', 'varchar(64) not null');
+$dbh->bz_change_field_type('bugs', 'bug_severity', 'varchar(64) not null');
+$dbh->bz_change_field_type('bugs', 'rep_platform', 'varchar(64) not null');
+$dbh->bz_change_field_type('bugs', 'op_sys', 'varchar(64) not null');
 
 
 # 2005-02-20 - LpSolit@gmail.com - Bug 277504
 # When migrating quips from the '$datadir/comments' file to the DB,
 # the user ID should be NULL instead of 0 (which is an invalid user ID).
-if (!GetFieldDef('quips', 'userid')->[2]) {
-    ChangeFieldType('quips', 'userid', 'mediumint null');
+if (!$dbh->bz_get_field_def('quips', 'userid')->[2]) {
+    $dbh->bz_change_field_type('quips', 'userid', 'mediumint null');
     print "Changing owner to NULL for quips where the owner is unknown...\n";
     $dbh->do('UPDATE quips SET userid = NULL WHERE userid = 0');
 }
@@ -4348,8 +4184,8 @@ if (!GetFieldDef('quips', 'userid')->[2]) {
 # table should therefore be marked as obsolete, meaning that they cannot
 # be used anymore when querying the database - they are not deleted in
 # order to keep track of these fields in the activity table.
-if (!GetFieldDef('fielddefs', 'obsolete')) {
-    AddField('fielddefs', 'obsolete', 'tinyint not null default 0');
+if (!$dbh->bz_get_field_def('fielddefs', 'obsolete')) {
+    $dbh->bz_add_field('fielddefs', 'obsolete', 'tinyint not null default 0');
     print "Marking qacontact_accessible and assignee_accessible as obsolete fields...\n";
     $dbh->do("UPDATE fielddefs SET obsolete = 1
               WHERE name = 'qacontact_accessible'
@@ -4363,8 +4199,8 @@ if (!GetFieldDef('fielddefs', 'obsolete')) {
 # That is: if you add a new field, you first search for the first occurrence
 # of --TABLE-- and add your field to into the table hash. This new setting
 # would be honored for every new installation. Then add your
-# AddField/DropField/ChangeFieldType/RenameField code above. This would then
-# be honored by everyone who updates his Bugzilla installation.
+# bz_add_field/bz_drop_field/bz_change_field_type/bz_rename_field code above. 
+# This would then be honored by everyone who updates his Bugzilla installation.
 #
 
 #
@@ -4666,11 +4502,11 @@ if ($sth->rows == 0) {
 }
 
 # Add fulltext indexes for bug summaries and descriptions/comments.
-if (!defined GetIndexDef('bugs', 'short_desc')) {
+if (!defined $dbh->bz_get_index_def('bugs', 'short_desc')) {
     print "Adding full-text index for short_desc column in bugs table...\n";
     $dbh->do('ALTER TABLE bugs ADD FULLTEXT (short_desc)');
 }
-if (!defined GetIndexDef('longdescs', 'thetext')) {
+if (!defined $dbh->bz_get_index_def('longdescs', 'thetext')) {
     print "Adding full-text index for thetext column in longdescs table...\n";
     $dbh->do('ALTER TABLE longdescs ADD FULLTEXT (thetext)');
 }
@@ -4684,7 +4520,7 @@ if (!defined GetIndexDef('longdescs', 'thetext')) {
 # and attachment.cgi now takes them out, but old ones need converting.
 #
 {
-    my $ref = GetFieldDef("attachments", "filename");
+    my $ref = $dbh->bz_get_field_def("attachments", "filename");
     if ($ref->[1] ne 'varchar(100)') {
         print "Removing paths from filenames in attachments table...\n";
         
@@ -4703,16 +4539,16 @@ if (!defined GetIndexDef('longdescs', 'thetext')) {
         print "Done.\n";
         
         print "Resizing attachments.filename from mediumtext to varchar(100).\n";
-        ChangeFieldType("attachments", "filename", "varchar(100) not null");
+        $dbh->bz_change_field_type("attachments", "filename", "varchar(100) not null");
     }
 }
 
 # 2003-01-11, burnus@net-b.de, bug 184309
 # Support for quips approval
-AddField('quips', 'approved', 'tinyint(1) NOT NULL  DEFAULT 1');
+$dbh->bz_add_field('quips', 'approved', 'tinyint(1) NOT NULL  DEFAULT 1');
  
 # 2002-12-20 Bug 180870 - remove manual shadowdb replication code
-if (TableExists('shadowlog')) {
+if ($dbh->bz_table_exists('shadowlog')) {
     print "Removing shadowlog table\n";
     $dbh->do("DROP TABLE shadowlog");
 }
@@ -4723,20 +4559,20 @@ if (TableExists('shadowlog')) {
 #
 # Renaming the 'count' column in the votes table because Sybase doesn't
 # like it
-if (GetFieldDef('votes', 'count')) {
+if ($dbh->bz_get_field_def('votes', 'count')) {
     # 2003-04-24 - myk@mozilla.org/bbaetz@acm.org, bug 201018
     # Force all cached groups to be updated at login, due to security bug
     # Do this here, inside the next schema change block, so that it doesn't
     # get invalidated on every checksetup run.
     $dbh->do("UPDATE profiles SET refreshed_when='1900-01-01 00:00:00'");
 
-    RenameField ('votes', 'count', 'vote_count');
+    $dbh->bz_rename_field('votes', 'count', 'vote_count');
 }
 
 # 2004/02/15 - Summaries shouldn't be null - see bug 220232
-if (GetFieldDef('bugs', 'short_desc')->[2]) { # if it allows nulls
+if ($dbh->bz_get_field_def('bugs', 'short_desc')->[2]) { # if it allows nulls
     $dbh->do("UPDATE bugs SET short_desc = '' WHERE short_desc IS NULL");
-    ChangeFieldType('bugs', 'short_desc', 'mediumtext not null');
+    $dbh->bz_change_field_type('bugs', 'short_desc', 'mediumtext not null');
 }
 
 # 2004-04-12 - Keep regexp-based group permissions up-to-date - Bug 240325
@@ -4787,7 +4623,7 @@ if ($emailflags_count) {
 
 # 2003-10-24 - alt@sonic.net, bug 224208
 # Support classification level and make sure there is a default classification
-AddField('products', 'classification_id', 'smallint DEFAULT 1');
+$dbh->bz_add_field('products', 'classification_id', 'smallint DEFAULT 1');
 $sth = $dbh->prepare("SELECT name FROM classifications WHERE id=1");
 $sth->execute;
 if (! $sth->rows) {
@@ -4797,9 +4633,9 @@ if (! $sth->rows) {
 
 # 2004-08-29 - Tomas.Kopal@altap.cz, bug 257303
 # Change logincookies.lastused type from timestamp to datetime
-if (($fielddef = GetFieldDef("logincookies", "lastused")) &&
+if (($fielddef = $dbh->bz_get_field_def("logincookies", "lastused")) &&
     $fielddef->[1] =~ /^timestamp/) {
-    ChangeFieldType ('logincookies', 'lastused', 'DATETIME NOT NULL');
+    $dbh->bz_change_field_type('logincookies', 'lastused', 'DATETIME NOT NULL');
 }
 
 # 2005-01-12 Nick Barnes <nb@ravenbrook.com> bug 278010
@@ -4834,17 +4670,17 @@ if ($emptygroupid) {
 
 # 2005-01-17 - Tomas.Kopal@altap.cz, bug 257315
 # Change bugs.delta_ts type from timestamp to datetime
-if (($fielddef = GetFieldDef("bugs", "delta_ts")) &&
+if (($fielddef = $dbh->bz_get_field_def("bugs", "delta_ts")) &&
     $fielddef->[1] =~ /^timestamp/) {
-    ChangeFieldType ('bugs', 'delta_ts', 'DATETIME NOT NULL');
+    $dbh->bz_change_field_type('bugs', 'delta_ts', 'DATETIME NOT NULL');
 }
 
 # 2005-02-12 bugreport@peshkin.net, bug 281787
-if (!defined GetIndexDef('attachments','submitter_id')) {
+if (!defined $dbh->bz_get_index_def('attachments','submitter_id')) {
     print "Adding index for submitter_id column in attachments table...\n";
     $dbh->do('ALTER TABLE attachments ADD INDEX (submitter_id)');
 }
-if (!defined GetIndexDef('bugs_activity','who')) {
+if (!defined $dbh->bz_get_index_def('bugs_activity','who')) {
     print "Adding index for who column in bugs_activity table...\n";
     $dbh->do('ALTER TABLE bugs_activity ADD INDEX (who)');
 }