summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormkanat%bugzilla.org <>2008-08-01 07:37:15 +0200
committermkanat%bugzilla.org <>2008-08-01 07:37:15 +0200
commit73a4dd56109c4799fd1d4ac7ed56ff72a47279bb (patch)
tree1b029a07667f48b1eb80507b815905ef9bb217f3
parentd165b7785df760352ce17d3677691c5be0b3b6c4 (diff)
downloadbugzilla-73a4dd56109c4799fd1d4ac7ed56ff72a47279bb.tar.gz
bugzilla-73a4dd56109c4799fd1d4ac7ed56ff72a47279bb.tar.xz
Bug 440188: buglist.cgi should display EXPLAIN output when &debug=1
Patch By Max Kanat-Alexander <mkanat@bugzilla.org> r=LpSolit, a=mkanat
-rw-r--r--Bugzilla/DB.pm2
-rw-r--r--Bugzilla/DB/Mysql.pm26
-rw-r--r--Bugzilla/DB/Oracle.pm9
-rw-r--r--Bugzilla/DB/Pg.pm6
-rwxr-xr-xbuglist.cgi7
-rw-r--r--skins/standard/buglist.css4
-rw-r--r--template/en/default/list/list.html.tmpl3
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' %]