Commit a0f148fa authored by Max Kanat-Alexander's avatar Max Kanat-Alexander

Bug 578299: Search.pm: Generate the GROUP BY clause in a method

r=mkanat, a=mkanat (module owner)
parent fe2d78c8
...@@ -340,6 +340,7 @@ use constant COLUMN_JOINS => { ...@@ -340,6 +340,7 @@ use constant COLUMN_JOINS => {
}, },
actual_time => { actual_time => {
table => 'longdescs', table => 'longdescs',
join => 'INNER',
}, },
'flagtypes.name' => { 'flagtypes.name' => {
name => 'map_flags', name => 'map_flags',
...@@ -502,6 +503,17 @@ sub REPORT_COLUMNS { ...@@ -502,6 +503,17 @@ sub REPORT_COLUMNS {
return $columns; return $columns;
} }
# These are fields that never go into the GROUP BY on any DB. bug_id
# is here because it *always* goes into the GROUP BY as the first item,
# so it should be skipped when determining extra GROUP BY columns.
use constant GROUP_BY_SKIP => EMPTY_COLUMN, qw(
actual_time
bug_id
flagtypes.name
keywords
percentage_complete
);
###################### ######################
# Internal Accessors # # Internal Accessors #
###################### ######################
...@@ -531,9 +543,9 @@ sub _multi_select_fields { ...@@ -531,9 +543,9 @@ sub _multi_select_fields {
return $self->{multi_select_fields}; return $self->{multi_select_fields};
} }
############################### ##############################
# Internal Accessors: Columns # # Internal Accessors: SELECT #
############################### ##############################
# These are the fields the user has chosen to display on the buglist, # These are the fields the user has chosen to display on the buglist,
# exactly as they were passed to new(). # exactly as they were passed to new().
...@@ -590,9 +602,9 @@ sub _sql_select { ...@@ -590,9 +602,9 @@ sub _sql_select {
return @sql_fields; return @sql_fields;
} }
############################# ################################
# Internal Accessors: Order # # Internal Accessors: ORDER BY #
############################# ################################
# The "order" that was requested by the consumer, exactly as it was # The "order" that was requested by the consumer, exactly as it was
# requested. # requested.
...@@ -638,9 +650,9 @@ sub _sql_order_by { ...@@ -638,9 +650,9 @@ sub _sql_order_by {
return @{ $self->{sql_order_by} }; return @{ $self->{sql_order_by} };
} }
################################### ############################
# Internal Accessors: FROM clause # # Internal Accessors: FROM #
################################### ############################
# JOIN statements for the SELECT and ORDER BY columns. This should not be called # JOIN statements for the SELECT and ORDER BY columns. This should not be called
# Until the moment it is needed, because _select_columns might be # Until the moment it is needed, because _select_columns might be
...@@ -662,6 +674,49 @@ sub _select_order_joins { ...@@ -662,6 +674,49 @@ sub _select_order_joins {
return @joins; return @joins;
} }
################################
# Internal Accessors: GROUP BY #
################################
# And these are the fields that we have to do GROUP BY for in DBs
# that are more strict about putting everything into GROUP BY.
sub _sql_group_by {
my ($self) = @_;
# Strict DBs require every element from the SELECT to be in the GROUP BY,
# unless that element is being used in an aggregate function.
my @extra_group_by;
foreach my $column ($self->_select_columns) {
next if $self->_skip_group_by->{$column};
my $sql = COLUMNS->{$column}->{name};
push(@extra_group_by, $sql);
}
# And all items from ORDER BY must be in the GROUP BY. The above loop
# doesn't catch items that were put into the ORDER BY from SPECIAL_ORDER.
foreach my $column ($self->_input_order_columns) {
my $special_order = $self->_special_order->{$column}->{order};
next if !$special_order;
push(@extra_group_by, @$special_order);
}
@extra_group_by = uniq @extra_group_by;
# bug_id is the only field we actually group by.
return ('bugs.bug_id', join(',', @extra_group_by));
}
# A helper for _sql_group_by.
sub _skip_group_by {
my ($self) = @_;
return $self->{skip_group_by} if $self->{skip_group_by};
my @skip_list = GROUP_BY_SKIP;
push(@skip_list, keys %{ $self->_multi_select_fields });
my %skip_hash = map { $_ => 1 } @skip_list;
$self->{skip_group_by} = \%skip_hash;
return $self->{skip_group_by};
}
################################## ##################################
# Helpers for Internal Accessors # # Helpers for Internal Accessors #
################################## ##################################
...@@ -746,7 +801,6 @@ sub init { ...@@ -746,7 +801,6 @@ sub init {
my @supptables; my @supptables;
my @wherepart; my @wherepart;
my @having; my @having;
my @groupby;
my @specialchart; my @specialchart;
my @andlist; my @andlist;
...@@ -1197,7 +1251,6 @@ sub init { ...@@ -1197,7 +1251,6 @@ sub init {
joins => \@supptables, joins => \@supptables,
where => \@wherepart, where => \@wherepart,
having => \@having, having => \@having,
group_by => \@groupby,
); );
# This should add a "term" selement to %search_args. # This should add a "term" selement to %search_args.
$self->do_search_function(\%search_args); $self->do_search_function(\%search_args);
...@@ -1285,28 +1338,7 @@ sub init { ...@@ -1285,28 +1338,7 @@ sub init {
} }
} }
# For some DBs, every field in the SELECT must be in the GROUP BY. $query .= ") " . $dbh->sql_group_by($self->_sql_group_by);
foreach my $field ($self->_select_columns) {
# These fields never go into the GROUP BY (bug_id goes in
# explicitly, below).
my @skip_group_by = (EMPTY_COLUMN,
qw(bug_id actual_time percentage_complete flagtypes.name
keywords));
push(@skip_group_by, keys %{ $self->_multi_select_fields });
next if grep { $_ eq $field } @skip_group_by;
my $col = COLUMNS->{$field}->{name};
push(@groupby, $col) if !grep($_ eq $col, @groupby);
}
# And all items from ORDER BY must be in the GROUP BY. The above loop
# doesn't catch items that were put into the ORDER BY from SPECIAL_ORDER.
foreach my $item ($self->_sql_order_by) {
my $column_name = split_order_term($item);
if (my $order = $self->_special_order->{$column_name}->{order}) {
push(@groupby, $order);
}
}
$query .= ") " . $dbh->sql_group_by("bugs.bug_id", join(', ', @groupby));
if (@having) { if (@having) {
...@@ -1760,8 +1792,8 @@ sub _long_desc_changedbefore_after { ...@@ -1760,8 +1792,8 @@ sub _long_desc_changedbefore_after {
sub _content_matches { sub _content_matches {
my ($self, $args) = @_; my ($self, $args) = @_;
my ($chart_id, $joins, $group_by, $fields, $operator, $value) = my ($chart_id, $joins, $fields, $operator, $value) =
@$args{qw(chart_id joins group_by fields operator value)}; @$args{qw(chart_id joins fields operator value)};
my $dbh = Bugzilla->dbh; my $dbh = Bugzilla->dbh;
# "content" is an alias for columns containing text for which we # "content" is an alias for columns containing text for which we
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment