summaryrefslogtreecommitdiffstats
path: root/Bugzilla/Search.pm
diff options
context:
space:
mode:
authorByron Jones <bjones@mozilla.com>2013-04-17 19:15:46 +0200
committerByron Jones <bjones@mozilla.com>2013-04-17 19:15:46 +0200
commitcd2776192dbaf1d21353f400eaf42d01e66b33f4 (patch)
tree18de730e2b1c4394eaacfdca8e468e4cf8e8d169 /Bugzilla/Search.pm
parent5151736ba38fb79a811972960753313691226928 (diff)
downloadbugzilla-cd2776192dbaf1d21353f400eaf42d01e66b33f4.tar.gz
bugzilla-cd2776192dbaf1d21353f400eaf42d01e66b33f4.tar.xz
Bug 828344: Make "contains all of the words" look for all words within the same comment or flag
r=LpSolit, a=LpSolit
Diffstat (limited to 'Bugzilla/Search.pm')
-rw-r--r--Bugzilla/Search.pm148
1 files changed, 117 insertions, 31 deletions
diff --git a/Bugzilla/Search.pm b/Bugzilla/Search.pm
index 658b85f99..51520bb55 100644
--- a/Bugzilla/Search.pm
+++ b/Bugzilla/Search.pm
@@ -268,12 +268,14 @@ use constant OPERATOR_FIELD_OVERRIDE => {
},
dependson => MULTI_SELECT_OVERRIDE,
keywords => MULTI_SELECT_OVERRIDE,
- 'flagtypes.name' => MULTI_SELECT_OVERRIDE,
+ 'flagtypes.name' => {
+ _non_changed => \&_flagtypes_nonchanged,
+ },
longdesc => {
- %{ MULTI_SELECT_OVERRIDE() },
changedby => \&_long_desc_changedby,
changedbefore => \&_long_desc_changedbefore_after,
changedafter => \&_long_desc_changedbefore_after,
+ _non_changed => \&_long_desc_nonchanged,
},
'longdescs.count' => {
changedby => \&_long_desc_changedby,
@@ -767,8 +769,16 @@ sub _sql {
my ($self) = @_;
return $self->{sql} if $self->{sql};
my $dbh = Bugzilla->dbh;
-
+
my ($joins, $clause) = $self->_charts_to_conditions();
+
+ if (!$clause->as_string
+ && !Bugzilla->params->{'search_allow_no_criteria'}
+ && !$self->{allow_unlimited})
+ {
+ ThrowUserError('buglist_parameters_required');
+ }
+
my $select = join(', ', $self->_sql_select);
my $from = $self->_sql_from($joins);
my $where = $self->_sql_where($clause);
@@ -1308,14 +1318,7 @@ sub _sql_where {
# SQL a bit more readable for debugging.
my $where = join("\n AND ", $self->_standard_where);
my $clause_sql = $main_clause->as_string;
- if ($clause_sql) {
- $where .= "\n AND " . $clause_sql;
- }
- elsif (!Bugzilla->params->{'search_allow_no_criteria'}
- && !$self->{allow_unlimited})
- {
- ThrowUserError('buglist_parameters_required');
- }
+ $where .= "\n AND " . $clause_sql if $clause_sql;
return $where;
}
@@ -1994,24 +1997,13 @@ sub _quote_unless_numeric {
sub build_subselect {
my ($outer, $inner, $table, $cond, $negate) = @_;
-
- if ($table eq 'longdescs') {
- # There is no index on the longdescs.thetext column and so it takes
- # a long time to scan the whole table unconditionally. For this table,
- # we return the subselect and let the DB optimizer restrict the search
- # to some given bug list only based on other search criteria available.
- my $not = $negate ? "NOT" : "";
- return "$outer $not IN (SELECT DISTINCT $inner FROM $table WHERE $cond)";
- }
- else {
- # Execute subselects immediately to avoid dependent subqueries, which are
- # large performance hits on MySql
- my $q = "SELECT DISTINCT $inner FROM $table WHERE $cond";
- my $dbh = Bugzilla->dbh;
- my $list = $dbh->selectcol_arrayref($q);
- return $negate ? "1=1" : "1=2" unless @$list;
- return $dbh->sql_in($outer, $list, $negate);
- }
+ # Execute subselects immediately to avoid dependent subqueries, which are
+ # large performance hits on MySql
+ my $q = "SELECT DISTINCT $inner FROM $table WHERE $cond";
+ my $dbh = Bugzilla->dbh;
+ my $list = $dbh->selectcol_arrayref($q);
+ return $negate ? "1=1" : "1=2" unless @$list;
+ return $dbh->sql_in($outer, $list, $negate);
}
# Used by anyexact to get the list of input values. This allows us to
@@ -2432,14 +2424,51 @@ sub _long_desc_changedbefore_after {
}
}
+sub _long_desc_nonchanged {
+ my ($self, $args) = @_;
+ my ($chart_id, $operator, $value, $joins, $bugs_table) =
+ @$args{qw(chart_id operator value joins bugs_table)};
+ my $dbh = Bugzilla->dbh;
+
+ my $table = "longdescs_$chart_id";
+ my $join_args = {
+ chart_id => $chart_id,
+ sequence => $chart_id,
+ field => 'longdesc',
+ full_field => "$table.thetext",
+ operator => $operator,
+ value => $value,
+ all_values => $value,
+ quoted => $dbh->quote($value),
+ joins => [],
+ bugs_table => $bugs_table,
+ };
+ $self->_do_operator_function($join_args);
+
+ # If the user is not part of the insiders group, they cannot see
+ # private comments
+ if (!$self->_user->is_insider) {
+ $join_args->{term} .= " AND $table.isprivate = 0";
+ }
+
+ my $join = {
+ table => 'longdescs',
+ as => $table,
+ extra => [ $join_args->{term} ],
+ };
+ push(@$joins, $join);
+
+ $args->{term} = "$table.comment_id IS NOT NULL";
+}
+
sub _content_matches {
my ($self, $args) = @_;
my ($chart_id, $joins, $fields, $operator, $value) =
@$args{qw(chart_id joins fields operator value)};
my $dbh = Bugzilla->dbh;
-
+
# "content" is an alias for columns containing text for which we
- # can search a full-text index and retrieve results by relevance,
+ # can search a full-text index and retrieve results by relevance,
# currently just bug comments (and summaries to some degree).
# There's only one way to search a full-text index, so we only
# accept the "matches" operator, which is specific to full-text
@@ -2694,6 +2723,63 @@ sub _multiselect_multiple {
}
}
+sub _flagtypes_nonchanged {
+ my ($self, $args) = @_;
+ my ($chart_id, $operator, $value, $joins, $bugs_table) =
+ @$args{qw(chart_id operator value joins bugs_table)};
+ my $dbh = Bugzilla->dbh;
+ my $join;
+
+ # join to the attachments table
+ my $attach_table = "attachments_$chart_id";
+ $join = {
+ table => 'attachments',
+ as => $attach_table,
+ from => "$bugs_table.bug_id",
+ to => "bug_id",
+ extra => [ ($self->_user->is_insider ? '' : "$attach_table.isprivate = 0") ],
+ };
+ push(@$joins, $join);
+
+ # join to the flags table
+ my $flags_table = "flags_$chart_id";
+ $join = {
+ table => 'flags',
+ as => $flags_table,
+ from => "$bugs_table.bug_id",
+ to => "bug_id",
+ extra => [ "($flags_table.attach_id = $attach_table.attach_id " .
+ " OR $flags_table.attach_id IS NULL)" ],
+ };
+ push(@$joins, $join);
+
+ # join to the flagtypes table
+ my $flagtypes_table = "flagtypes_$chart_id";
+ $join = {
+ table => 'flagtypes',
+ as => $flagtypes_table,
+ from => "$flags_table.type_id",
+ to => "id",
+ };
+ push(@$joins, $join);
+
+ # join to the profiles table for the requestee
+ my $flag_profile_table = "flag_profiles_$chart_id";
+ $join = {
+ table => 'profiles',
+ as => $flag_profile_table,
+ from => "$flags_table.requestee_id",
+ to => "userid",
+ };
+ push(@$joins, $join);
+
+ $args->{full_field} = $dbh->sql_string_concat("$flagtypes_table.name",
+ "$flags_table.status",
+ "COALESCE($flag_profile_table.login_name, '')");
+
+ $self->_do_operator_function($args);
+}
+
sub _multiselect_nonchanged {
my ($self, $args) = @_;
my ($chart_id, $joins, $field, $operator) =