diff options
-rw-r--r-- | Bugzilla/DB.pm | 2 | ||||
-rw-r--r-- | Bugzilla/DB/Mysql.pm | 26 | ||||
-rw-r--r-- | Bugzilla/DB/Oracle.pm | 9 | ||||
-rw-r--r-- | Bugzilla/DB/Pg.pm | 6 | ||||
-rwxr-xr-x | buglist.cgi | 7 | ||||
-rw-r--r-- | skins/standard/buglist.css | 4 | ||||
-rw-r--r-- | template/en/default/list/list.html.tmpl | 3 |
7 files changed, 56 insertions, 1 deletions
diff --git a/Bugzilla/DB.pm b/Bugzilla/DB.pm index b23c865c1..399f3c643 100644 --- a/Bugzilla/DB.pm +++ b/Bugzilla/DB.pm @@ -273,7 +273,7 @@ EOT # List of abstract methods we are checking the derived class implements our @_abstract_methods = qw(REQUIRED_VERSION PROGRAM_NAME DBD_VERSION new sql_regexp sql_not_regexp sql_limit sql_to_days - sql_date_format sql_interval); + sql_date_format sql_interval bz_explain); # This overridden import method will check implementation of inherited classes # for missing implementation of abstract methods diff --git a/Bugzilla/DB/Mysql.pm b/Bugzilla/DB/Mysql.pm index 8a64d3646..fdb475078 100644 --- a/Bugzilla/DB/Mysql.pm +++ b/Bugzilla/DB/Mysql.pm @@ -48,6 +48,8 @@ use Bugzilla::Util; use Bugzilla::Error; use Bugzilla::DB::Schema::Mysql; +use List::Util qw(max); + # This module extends the DB interface via inheritance use base qw(Bugzilla::DB); @@ -204,6 +206,30 @@ sub sql_group_by { return "GROUP BY $needed_columns"; } +sub bz_explain { + my ($self, $sql) = @_; + my $sth = $self->prepare("EXPLAIN $sql"); + $sth->execute(); + my $columns = $sth->{'NAME'}; + my $lengths = $sth->{'mysql_max_length'}; + my $format_string = '|'; + my $i = 0; + foreach my $column (@$columns) { + # Sometimes the column name is longer than the contents. + my $length = max($lengths->[$i], length($column)); + $format_string .= ' %-' . $length . 's |'; + $i++; + } + + my $first_row = sprintf($format_string, @$columns); + my @explain_rows = ($first_row, '-' x length($first_row)); + while (my $row = $sth->fetchrow_arrayref) { + my @fixed = map { defined $_ ? $_ : 'NULL' } @$row; + push(@explain_rows, sprintf($format_string, @fixed)); + } + + return join("\n", @explain_rows); +} sub _bz_get_initial_schema { my ($self) = @_; diff --git a/Bugzilla/DB/Oracle.pm b/Bugzilla/DB/Oracle.pm index 56d9d3fbf..341818a5c 100644 --- a/Bugzilla/DB/Oracle.pm +++ b/Bugzilla/DB/Oracle.pm @@ -104,6 +104,15 @@ sub bz_check_regexp { { value => $pattern, dberror => $self->errstr }); } +sub bz_explain { + my ($self, $sql) = @_; + my $sth = $self->prepare("EXPLAIN PLAN FOR $sql"); + $sth->execute(); + my $explain = $self->selectcol_arrayref( + "SELECT PLAN_TABLE_OUTPUT FROM TABLE(DBMS_XPLAN.DISPLAY)"); + return join("\n", @$explain); +} + sub sql_regexp { my ($self, $expr, $pattern, $nocheck) = @_; diff --git a/Bugzilla/DB/Pg.pm b/Bugzilla/DB/Pg.pm index a6a2e3281..d06decaa3 100644 --- a/Bugzilla/DB/Pg.pm +++ b/Bugzilla/DB/Pg.pm @@ -171,6 +171,12 @@ sub bz_sequence_exists { return $exists || 0; } +sub bz_explain { + my ($self, $sql) = @_; + my $explain = $self->selectcol_arrayref("EXPLAIN ANALYZE $sql"); + return join("\n", @$explain); +} + ##################################################################### # Custom Database Setup ##################################################################### diff --git a/buglist.cgi b/buglist.cgi index 86147869b..114523286 100755 --- a/buglist.cgi +++ b/buglist.cgi @@ -994,6 +994,13 @@ elsif ($fulltext) { if ($cgi->param('debug')) { $vars->{'debug'} = 1; $vars->{'query'} = $query; + # Explains are limited to admins because you could use them to figure + # out how many hidden bugs are in a particular product (by doing + # searches and looking at the number of rows the explain says it's + # examining). + if (Bugzilla->user->in_group('admin')) { + $vars->{'query_explain'} = $dbh->bz_explain($query); + } $vars->{'debugdata'} = $search->getDebugData(); } diff --git a/skins/standard/buglist.css b/skins/standard/buglist.css index 71206fcbd..ca37dc763 100644 --- a/skins/standard/buglist.css +++ b/skins/standard/buglist.css @@ -64,3 +64,7 @@ tr.bz_secure_mode_manual td.first-child { #commit, #action { margin-top: .25em; } + +.bz_query_explain { + text-align: left; +} diff --git a/template/en/default/list/list.html.tmpl b/template/en/default/list/list.html.tmpl index 0a8eb402c..512201c27 100644 --- a/template/en/default/list/list.html.tmpl +++ b/template/en/default/list/list.html.tmpl @@ -68,6 +68,9 @@ [% END %] </p> <p class="bz_query">[% query FILTER html %]</p> + [% IF query_explain.defined %] + <pre class="bz_query_explain">[% query_explain FILTER html %]</pre> + [% END %] [% END %] [% IF user.settings.display_quips.value == 'on' %] |