From 0ac4d26f78657a3bb089711cac2fd5f76d077437 Mon Sep 17 00:00:00 2001 From: Max Kanat-Alexander Date: Tue, 1 Jun 2010 13:33:49 -0700 Subject: Bug 569312: Speed up the adding of many FKs to the same table for MySQL and PostgreSQL, by adding them all in one ALTER statement r=mkanat, a=mkanat (module owner) --- Bugzilla/DB/Schema/Oracle.pm | 63 ++++++++++++++++++++++++-------------------- 1 file changed, 34 insertions(+), 29 deletions(-) (limited to 'Bugzilla/DB/Schema') diff --git a/Bugzilla/DB/Schema/Oracle.pm b/Bugzilla/DB/Schema/Oracle.pm index e8905eb80..af0c11e9f 100644 --- a/Bugzilla/DB/Schema/Oracle.pm +++ b/Bugzilla/DB/Schema/Oracle.pm @@ -35,6 +35,7 @@ use Carp qw(confess); use Bugzilla::Util; use constant ADD_COLUMN => 'ADD'; +use constant MULTIPLE_FKS_IN_ALTER => 0; # Whether this is true or not, this is what it needs to be in order for # hash_identifier to maintain backwards compatibility with versions before # 3.2rc2. @@ -136,40 +137,44 @@ sub get_drop_index_ddl { # - Delete CASCADE # - Delete SET NULL sub get_fk_ddl { - my ($self, $table, $column, $references) = @_; - return "" if !$references; + my $self = shift; + my $ddl = $self->SUPER::get_fk_ddl(@_); - my $update = $references->{UPDATE} || 'CASCADE'; - my $delete = $references->{DELETE}; - my $to_table = $references->{TABLE} || confess "No table in reference"; - my $to_column = $references->{COLUMN} || confess "No column in reference"; - my $fk_name = $self->_get_fk_name($table, $column, $references); + # iThe Bugzilla Oracle driver implements UPDATE via a trigger. + $ddl =~ s/ON UPDATE \S+//i; + # RESTRICT is the default for DELETE on Oracle and may not be specified. + $ddl =~ s/ON DELETE RESTRICT//i; - # 'ON DELETE RESTRICT' is enabled by default - $delete = "" if ( defined $delete && $delete =~ /RESTRICT/i); + return $ddl; +} - my $fk_string = "\n CONSTRAINT $fk_name FOREIGN KEY ($column)\n" - . " REFERENCES $to_table($to_column)\n"; - - $fk_string = $fk_string . " ON DELETE $delete" if $delete; - - if ( $update =~ /CASCADE/i ){ - my $tr_str = "CREATE OR REPLACE TRIGGER ${fk_name}_UC" - . " AFTER UPDATE OF $to_column ON $to_table " - . " REFERENCING " - . " NEW AS NEW " - . " OLD AS OLD " - . " FOR EACH ROW " - . " BEGIN " - . " UPDATE $table" - . " SET $column = :NEW.$to_column" - . " WHERE $column = :OLD.$to_column;" - . " END ${fk_name}_UC;"; - my $dbh = Bugzilla->dbh; - $dbh->do($tr_str); +sub get_add_fks_sql { + my $self = shift; + my ($table, $column_fks) = @_; + my @sql = $self->SUPER::get_add_fks_sql(@_); + + foreach my $column (keys %$column_fks) { + my $fk = $column_fks->{$column}; + next if $fk->{UPDATE} && uc($fk->{UPDATE}) ne 'CASCADE'; + my $fk_name = $self->_get_fk_name($table, $column, $fk); + my $to_column = $fk->{COLUMN}; + my $to_table = $fk->{TABLE}; + + my $trigger = <