Bug 179451 : Move order-by generation from buglist.cgi into search.pm

Patch by Max K-A <mkanat@kerio.com>
r=Joel Peshkin <bugreport@peshkin.net>      a=myk
This commit is contained in:
travis%sedsystems.ca 2005-01-18 17:25:02 +00:00
Родитель ee77b80a96
Коммит d508450771
2 изменённых файлов: 112 добавлений и 15 удалений

Просмотреть файл

@ -24,6 +24,7 @@
# Andreas Franke <afranke@mathweb.org>
# Myk Melez <myk@mozilla.org>
# Michael Schindler <michael@compressconsult.com>
# Max Kanat-Alexander <mkanat@kerio.com>
use strict;
@ -43,17 +44,32 @@ use Bugzilla::Constants;
use Date::Format;
use Date::Parse;
# Some fields are not sorted on themselves, but on other fields.
# We need to have a list of these fields and what they map to.
# Each field points to an array that contains the fields mapped
# to, in order.
our %specialorder = (
'bugs.target_milestone' => [ 'ms_order.sortkey','ms_order.value' ]
);
# When we add certain fields to the ORDER BY, we need to then add a
# table join to the FROM statement. This hash maps input fields to
# the join statements that ned to be added.
our %specialorderjoin = (
'bugs.target_milestone' => 'LEFT JOIN milestones AS ms_order ON ms_order.value = bugs.target_milestone AND ms_order.product_id = bugs.product_id'
);
# Create a new Search
# Note that the param argument may be modified by Bugzilla::Search
sub new {
my $invocant = shift;
my $class = ref($invocant) || $invocant;
my $self = { @_ };
my $self = { @_ };
bless($self, $class);
$self->init();
return $self;
}
@ -63,8 +79,13 @@ sub init {
my $params = $self->{'params'};
my $user = $self->{'user'} || Bugzilla->user;
my $orderref = $self->{'order'} || 0;
my @inputorder;
@inputorder = @$orderref if $orderref;
my @orderby;
my $debug = 0;
my @fields;
my @supptables;
my @wherepart;
@ -1231,6 +1252,26 @@ sub init {
}
}
}
# The ORDER BY clause goes last, but can require modifications
# to other parts of the query, so we want to create it before we
# write the FROM clause.
foreach my $orderitem (@inputorder) {
BuildOrderBy($orderitem, \@orderby);
}
# Now JOIN the correct tables in the FROM clause.
# This is done separately from the above because it's
# cleaner to do it this way.
foreach my $orderitem (@inputorder) {
# Grab the part without ASC or DESC.
my @splitfield = split(/\s+/, $orderitem);
if ($specialorderjoin{$splitfield[0]}) {
push(@supptables, $specialorderjoin{$splitfield[0]});
}
# FIXME: Some DBs require ORDER BY items to also
# be in GROUP BY.
}
my %suppseen = ("bugs" => 1);
my $suppstring = "bugs";
my @supplist = (" ");
@ -1255,7 +1296,7 @@ sub init {
# Make sure we create a legal SQL query.
@andlist = ("1 = 1") if !@andlist;
my $query = "SELECT " . join(', ', @fields) .
" FROM $suppstring" .
" LEFT JOIN bug_group_map " .
@ -1288,6 +1329,10 @@ sub init {
$query .= " HAVING " . join(" AND ", @having);
}
if (@orderby) {
$query .= " ORDER BY " . join(',', @orderby);
}
if ($debug) {
print "<p><code>" . value_quote($query) . "</code></p>\n";
exit;
@ -1475,4 +1520,58 @@ sub IsValidQueryType
}
return 0;
}
# BuildOrderBy - Private Subroutine
# This function converts the input order to an "output" order,
# suitable for concatenation to form an ORDER BY clause. Basically,
# it just handles fields that have non-standard sort orders from
# %specialorder.
# Arguments:
# $orderitem - A string. The next value to append to the ORDER BY clause,
# in the format of an item in the 'order' parameter to
# Bugzilla::Search.
# $stringlist - A reference to the list of strings that will be join()'ed
# to make ORDER BY. This is what the subroutine modifies.
# $reverseorder - (Optional) A boolean. TRUE if we should reverse the order
# of the field that we are given (from ASC to DESC or vice-versa).
#
# Explanation of $reverseorder
# ----------------------------
# The role of $reverseorder is to handle things like sorting by
# "target_milestone DESC".
# Let's say that we had a field "A" that normally translates to a sort
# order of "B ASC, C DESC". If we sort by "A DESC", what we really then
# mean is "B DESC, C ASC". So $reverseorder is only used if we call
# BuildOrderBy recursively, to let it know that we're "reversing" the
# order. That is, that we wanted "A DESC", not "A".
sub BuildOrderBy {
my ($orderitem, $stringlist, $reverseorder) = (@_);
my @twopart = split(/\s+/, $orderitem);
my $orderfield = $twopart[0];
my $orderdirection = $twopart[1] || "";
if ($reverseorder) {
# If orderdirection is empty or ASC...
if (!$orderdirection || $orderdirection =~ m/asc/i) {
$orderdirection = "DESC";
} else {
# This has the minor side-effect of making any reversed invalid
# direction into ASC.
$orderdirection = "ASC";
}
}
# Handle fields that have non-standard sort orders, from $specialorder.
if ($specialorder{$orderfield}) {
foreach my $subitem (@{$specialorder{$orderfield}}) {
# DESC on a field with non-standard sort order means
# "reverse the normal order for each field that we map to."
BuildOrderBy($subitem, $stringlist, $orderdirection =~ m/desc/i);
}
return;
}
push(@$stringlist, $orderfield . ' ' . $orderdirection);
}
1;

Просмотреть файл

@ -23,6 +23,7 @@
# Stephan Niemz <st.n@gmx.net>
# Andreas Franke <afranke@mathweb.org>
# Myk Melez <myk@mozilla.org>
# Max Kanat-Alexander <mkanat@kerio.com>
################################################################################
# Script Initialization
@ -706,20 +707,17 @@ $db_order =~ s/$aggregate_search/actual_time/g;
$aggregate_search = quotemeta($columns->{'percentage_complete'}->{'name'});
$db_order =~ s/$aggregate_search/percentage_complete/g;
# Now put $db_order into a format that Bugzilla::Search can use.
# (We create $db_order as a string first because that's the way
# we did it before Bugzilla::Search took an "order" argument.)
my @orderstrings = split(',', $db_order);
# Generate the basic SQL query that will be used to generate the bug list.
my $search = new Bugzilla::Search('fields' => \@selectnames,
'params' => $params);
'params' => $params,
'order' => \@orderstrings);
my $query = $search->getSQL();
# Extra special disgusting hack: if we are ordering by target_milestone,
# change it to order by the sortkey of the target_milestone first.
if ($db_order =~ /bugs.target_milestone/) {
$db_order =~ s/bugs.target_milestone/ms_order.sortkey,ms_order.value/;
$query =~ s/\sWHERE\s/ LEFT JOIN milestones ms_order ON ms_order.value = bugs.target_milestone AND ms_order.product_id = bugs.product_id WHERE /;
}
$query .= " ORDER BY $db_order " if ($order);
if ($::FORM{'limit'} && detaint_natural($::FORM{'limit'})) {
$query .= " LIMIT $::FORM{'limit'}";
}