Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
bugzilla
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
etersoft
bugzilla
Commits
0ac4d26f
Commit
0ac4d26f
authored
Jun 01, 2010
by
Max Kanat-Alexander
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
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)
parent
cef81246
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
89 additions
and
47 deletions
+89
-47
DB.pm
Bugzilla/DB.pm
+33
-14
Schema.pm
Bugzilla/DB/Schema.pm
+22
-4
Oracle.pm
Bugzilla/DB/Schema/Oracle.pm
+34
-29
No files found.
Bugzilla/DB.pm
View file @
0ac4d26f
...
@@ -447,12 +447,14 @@ sub bz_setup_foreign_keys {
...
@@ -447,12 +447,14 @@ sub bz_setup_foreign_keys {
my
@tables
=
$self
->
_bz_schema
->
get_table_list
();
my
@tables
=
$self
->
_bz_schema
->
get_table_list
();
foreach
my
$table
(
@tables
)
{
foreach
my
$table
(
@tables
)
{
my
@columns
=
$self
->
_bz_schema
->
get_table_columns
(
$table
);
my
@columns
=
$self
->
_bz_schema
->
get_table_columns
(
$table
);
my
%
add_fks
;
foreach
my
$column
(
@columns
)
{
foreach
my
$column
(
@columns
)
{
my
$def
=
$self
->
_bz_schema
->
get_column_abstract
(
$table
,
$column
);
my
$def
=
$self
->
_bz_schema
->
get_column_abstract
(
$table
,
$column
);
if
(
$def
->
{
REFERENCES
})
{
if
(
$def
->
{
REFERENCES
})
{
$
self
->
bz_add_fk
(
$table
,
$column
,
$def
->
{
REFERENCES
})
;
$
add_fks
{
$column
}
=
$def
->
{
REFERENCES
}
;
}
}
}
}
$self
->
bz_add_fks
(
$table
,
\%
add_fks
);
}
}
}
}
...
@@ -506,19 +508,36 @@ sub bz_add_column {
...
@@ -506,19 +508,36 @@ sub bz_add_column {
sub
bz_add_fk
{
sub
bz_add_fk
{
my
(
$self
,
$table
,
$column
,
$def
)
=
@_
;
my
(
$self
,
$table
,
$column
,
$def
)
=
@_
;
$self
->
bz_add_fks
(
$table
,
{
$column
=>
$def
});
}
my
$col_def
=
$self
->
bz_column_info
(
$table
,
$column
);
sub
bz_add_fks
{
if
(
!
$col_def
->
{
REFERENCES
})
{
my
(
$self
,
$table
,
$column_fks
)
=
@_
;
$self
->
_check_references
(
$table
,
$column
,
$def
);
my
%
add_these
;
foreach
my
$column
(
keys
%
$column_fks
)
{
my
$col_def
=
$self
->
bz_column_info
(
$table
,
$column
);
next
if
$col_def
->
{
REFERENCES
};
my
$fk
=
$column_fks
->
{
$column
};
$self
->
_check_references
(
$table
,
$column
,
$fk
);
$add_these
{
$column
}
=
$fk
;
print
get_text
(
'install_fk_add'
,
print
get_text
(
'install_fk_add'
,
{
table
=>
$table
,
column
=>
$column
,
fk
=>
$
def
})
{
table
=>
$table
,
column
=>
$column
,
fk
=>
$
fk
})
.
"\n"
if
Bugzilla
->
usage_mode
==
USAGE_MODE_CMDLINE
;
.
"\n"
if
Bugzilla
->
usage_mode
==
USAGE_MODE_CMDLINE
;
my
@sql
=
$self
->
_bz_real_schema
->
get_add_fk_sql
(
$table
,
$column
,
$def
);
}
$self
->
do
(
$_
)
foreach
@sql
;
$col_def
->
{
REFERENCES
}
=
$def
;
return
if
!
scalar
(
keys
%
add_these
);
my
@sql
=
$self
->
_bz_real_schema
->
get_add_fks_sql
(
$table
,
\%
add_these
);
$self
->
do
(
$_
)
foreach
@sql
;
foreach
my
$column
(
keys
%
add_these
)
{
my
$col_def
=
$self
->
bz_column_info
(
$table
,
$column
);
$col_def
->
{
REFERENCES
}
=
$add_these
{
$column
};
$self
->
_bz_real_schema
->
set_column
(
$table
,
$column
,
$col_def
);
$self
->
_bz_real_schema
->
set_column
(
$table
,
$column
,
$col_def
);
$self
->
_bz_store_real_schema
;
}
}
$self
->
_bz_store_real_schema
();
}
}
sub
bz_alter_column
{
sub
bz_alter_column
{
...
@@ -700,11 +719,11 @@ sub bz_add_field_tables {
...
@@ -700,11 +719,11 @@ sub bz_add_field_tables {
$self
->
_bz_add_field_table
(
$ms_table
,
$self
->
_bz_add_field_table
(
$ms_table
,
$self
->
_bz_schema
->
MULTI_SELECT_VALUE_TABLE
);
$self
->
_bz_schema
->
MULTI_SELECT_VALUE_TABLE
);
$self
->
bz_add_fk
(
$ms_table
,
'bug_id'
,
{
TABLE
=>
'bugs'
,
$self
->
bz_add_fk
s
(
$ms_table
,
COLUMN
=>
'bug_id'
,
{
bug_id
=>
{
TABLE
=>
'bugs'
,
COLUMN
=>
'bug_id'
,
DELETE
=>
'CASCADE'
});
DELETE
=>
'CASCADE'
},
$self
->
bz_add_fk
(
$ms_table
,
'value'
,
{
TABLE
=>
$field
->
name
,
COLUMN
=>
'value'
});
value
=>
{
TABLE
=>
$field
->
name
,
COLUMN
=>
'value'
}
});
}
}
}
}
...
...
Bugzilla/DB/Schema.pm
View file @
0ac4d26f
...
@@ -210,6 +210,9 @@ update this column in this table."
...
@@ -210,6 +210,9 @@ update this column in this table."
use
constant
SCHEMA_VERSION
=>
'2.00'
;
use
constant
SCHEMA_VERSION
=>
'2.00'
;
use
constant
ADD_COLUMN
=>
'ADD COLUMN'
;
use
constant
ADD_COLUMN
=>
'ADD COLUMN'
;
# Multiple FKs can be added using ALTER TABLE ADD CONSTRAINT in one
# SQL statement. This isn't true for all databases.
use
constant
MULTIPLE_FKS_IN_ALTER
=>
1
;
# This is a reasonable default that's true for both PostgreSQL and MySQL.
# This is a reasonable default that's true for both PostgreSQL and MySQL.
use
constant
MAX_IDENTIFIER_LEN
=>
63
;
use
constant
MAX_IDENTIFIER_LEN
=>
63
;
...
@@ -1817,11 +1820,26 @@ sub _hash_identifier {
...
@@ -1817,11 +1820,26 @@ sub _hash_identifier {
}
}
sub
get_add_fk_sql
{
sub
get_add_fk
s
_sql
{
my
(
$self
,
$table
,
$column
,
$def
)
=
@_
;
my
(
$self
,
$table
,
$column
_fks
)
=
@_
;
my
$fk_string
=
$self
->
get_fk_ddl
(
$table
,
$column
,
$def
);
my
@add
;
return
(
"ALTER TABLE $table ADD $fk_string"
);
foreach
my
$column
(
keys
%
$column_fks
)
{
my
$def
=
$column_fks
->
{
$column
};
my
$fk_string
=
$self
->
get_fk_ddl
(
$table
,
$column
,
$def
);
push
(
@add
,
$fk_string
);
}
my
@sql
;
if
(
$self
->
MULTIPLE_FKS_IN_ALTER
)
{
my
$alter
=
"ALTER TABLE $table ADD "
.
join
(
', ADD '
,
@add
);
push
(
@sql
,
$alter
);
}
else
{
foreach
my
$fk_string
(
@add
)
{
push
(
@sql
,
"ALTER TABLE $table ADD $fk_string"
);
}
}
return
@sql
;
}
}
sub
get_drop_fk_sql
{
sub
get_drop_fk_sql
{
...
...
Bugzilla/DB/Schema/Oracle.pm
View file @
0ac4d26f
...
@@ -35,6 +35,7 @@ use Carp qw(confess);
...
@@ -35,6 +35,7 @@ use Carp qw(confess);
use
Bugzilla::
Util
;
use
Bugzilla::
Util
;
use
constant
ADD_COLUMN
=>
'ADD'
;
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
# 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
# hash_identifier to maintain backwards compatibility with versions before
# 3.2rc2.
# 3.2rc2.
...
@@ -136,40 +137,44 @@ sub get_drop_index_ddl {
...
@@ -136,40 +137,44 @@ sub get_drop_index_ddl {
# - Delete CASCADE
# - Delete CASCADE
# - Delete SET NULL
# - Delete SET NULL
sub
get_fk_ddl
{
sub
get_fk_ddl
{
my
(
$self
,
$table
,
$column
,
$references
)
=
@_
;
my
$self
=
shift
;
return
""
if
!
$references
;
my
$ddl
=
$self
->
SUPER::
get_fk_ddl
(
@_
)
;
my
$update
=
$references
->
{
UPDATE
}
||
'CASCADE'
;
# iThe Bugzilla Oracle driver implements UPDATE via a trigger.
my
$delete
=
$references
->
{
DELETE
};
$ddl
=~
s/ON UPDATE \S+//i
;
my
$to_table
=
$references
->
{
TABLE
}
||
confess
"No table in reference"
;
# RESTRICT is the default for DELETE on Oracle and may not be specified.
my
$to_column
=
$references
->
{
COLUMN
}
||
confess
"No column in reference"
;
$ddl
=~
s/ON DELETE RESTRICT//i
;
my
$fk_name
=
$self
->
_get_fk_name
(
$table
,
$column
,
$references
);
# 'ON DELETE RESTRICT' is enabled by default
return
$ddl
;
$delete
=
""
if
(
defined
$delete
&&
$delete
=~
/RESTRICT/i
);
}
my
$fk_string
=
"\n CONSTRAINT $fk_name FOREIGN KEY ($column)\n"
sub
get_add_fks_sql
{
.
" REFERENCES $to_table($to_column)\n"
;
my
$self
=
shift
;
my
(
$table
,
$column_fks
)
=
@_
;
$fk_string
=
$fk_string
.
" ON DELETE $delete"
if
$delete
;
my
@sql
=
$self
->
SUPER::
get_add_fks_sql
(
@_
);
if
(
$update
=~
/CASCADE/i
){
foreach
my
$column
(
keys
%
$column_fks
)
{
my
$tr_str
=
"CREATE OR REPLACE TRIGGER ${fk_name}_UC"
my
$fk
=
$column_fks
->
{
$column
};
.
" AFTER UPDATE OF $to_column ON $to_table "
next
if
$fk
->
{
UPDATE
}
&&
uc
(
$fk
->
{
UPDATE
})
ne
'CASCADE'
;
.
" REFERENCING "
my
$fk_name
=
$self
->
_get_fk_name
(
$table
,
$column
,
$fk
);
.
" NEW AS NEW "
my
$to_column
=
$fk
->
{
COLUMN
};
.
" OLD AS OLD "
my
$to_table
=
$fk
->
{
TABLE
};
.
" FOR EACH ROW "
.
" BEGIN "
my
$trigger
=
<<END;
.
" UPDATE $table"
CREATE OR REPLACE TRIGGER ${fk_name}_UC
.
" SET $column = :NEW.$to_column"
AFTER UPDATE OF $to_column ON $to_table
.
" WHERE $column = :OLD.$to_column;"
REFERENCING NEW AS NEW OLD AS OLD
.
" END ${fk_name}_UC;"
;
FOR EACH ROW
my
$dbh
=
Bugzilla
->
dbh
;
BEGIN
$dbh
->
do
(
$tr_str
);
UPDATE $table
SET $column = :NEW.$to_column
WHERE $column = :OLD.$to_column;
END ${fk_name}_UC;
END
push
(
@sql
,
$trigger
);
}
}
return
$fk_string
;
return
@sql
;
}
}
sub
get_drop_fk_sql
{
sub
get_drop_fk_sql
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment