diff options
-rw-r--r-- | Bugzilla/Search.pm | 67 | ||||
-rwxr-xr-x | query.cgi | 2 |
2 files changed, 67 insertions, 2 deletions
diff --git a/Bugzilla/Search.pm b/Bugzilla/Search.pm index 33cc1135e..709033a26 100644 --- a/Bugzilla/Search.pm +++ b/Bugzilla/Search.pm @@ -123,6 +123,9 @@ sub init { my @select_fields = Bugzilla->get_fields({ type => FIELD_TYPE_SINGLE_SELECT, obsolete => 0 }); + + my @multi_select_fields = Bugzilla->get_fields({ type => FIELD_TYPE_MULTI_SELECT, + obsolete => 0 }); foreach my $field (@select_fields) { my $name = $field->name; $special_order{"bugs.$name"} = [ "$name.sortkey", "$name.value" ], @@ -228,6 +231,7 @@ sub init { # Include custom select fields. push(@legal_fields, map { $_->name } @select_fields); + push(@legal_fields, map { $_->name } @multi_select_fields); foreach my $field ($params->param()) { if (lsearch(\@legal_fields, $field) != -1) { @@ -412,6 +416,8 @@ sub init { push(@specialchart, ['content', 'matches', $params->param('content')]); } + my $multi_fields = join('|', map($_->name, @multi_select_fields)); + my $chartid; my $sequence = 0; # $type_id is used by the code that queries for attachment flags. @@ -482,6 +488,9 @@ sub init { "^blocked,(?!changed)" => \&_blocked_nonchanged, "^alias,(?!changed)" => \&_alias_nonchanged, "^owner_idle_time,(greaterthan|lessthan)" => \&_owner_idle_time_greater_less, + "^($multi_fields),(?:notequals|notregexp|notsubstring|nowords|nowordssubstr)" => \&_multiselect_negative, + "^($multi_fields),(?:allwords|allwordssubstr|anyexact)" => \&_multiselect_multiple, + "^($multi_fields),(?!changed)" => \&_multiselect_nonchanged, ",equals" => \&_equals, ",notequals" => \&_notequals, ",casesubstring" => \&_casesubstring, @@ -1881,6 +1890,64 @@ sub _owner_idle_time_greater_less { $$term = "0=0"; } +sub _multiselect_negative { + my $self = shift; + my %func_args = @_; + my ($f, $ff, $t, $funcsbykey, $term) = @func_args{qw(f ff t funcsbykey term)}; + + my %map = ( + notequals => 'equals', + notregexp => 'regexp', + notsubstring => 'substring', + nowords => 'anywords', + nowordssubstr => 'anywordssubstr', + ); + + my $table = "bug_$$f"; + $$ff = "$table.value"; + + $$funcsbykey{",".$map{$$t}}($self, %func_args); + $$term = "bugs.bug_id NOT IN (SELECT bug_id FROM $table WHERE $$term)"; +} + +sub _multiselect_multiple { + my $self = shift; + my %func_args = @_; + my ($f, $ff, $t, $v, $funcsbykey, $term) = @func_args{qw(f ff t v funcsbykey term)}; + + my @terms; + my $table = "bug_$$f"; + $$ff = "$table.value"; + + foreach my $word (split(/[\s,]+/, $$v)) { + $$v = $word; + $$funcsbykey{",".$$t}($self, %func_args); + push(@terms, "bugs.bug_id IN + (SELECT bug_id FROM $table WHERE $$term)"); + } + + if ($$t eq 'anyexact') { + $$term = "(" . join(" OR ", @terms) . ")"; + } + else { + $$term = "(" . join(" AND ", @terms) . ")"; + } +} + +sub _multiselect_nonchanged { + my $self = shift; + my %func_args = @_; + my ($chartid, $f, $ff, $t, $funcsbykey, $supptables) = + @func_args{qw(chartid f ff t funcsbykey supptables)}; + + my $table = $$f."_".$$chartid; + $$ff = "$table.value"; + + $$funcsbykey{",$$t"}($self, %func_args); + push(@$supptables, "LEFT JOIN bug_$$f AS $table " . + "ON $table.bug_id = bugs.bug_id "); +} + sub _equals { my $self = shift; my %func_args = @_; @@ -260,8 +260,6 @@ $vars->{'bug_severity'} = get_legal_field_values('bug_severity'); # Boolean charts my @fields = Bugzilla->get_fields({ obsolete => 0 }); -# Multi-selects aren't searchable, currently. -@fields = grep($_->type != FIELD_TYPE_MULTI_SELECT, @fields); # If we're not in the time-tracking group, exclude time-tracking fields. if (!Bugzilla->user->in_group(Bugzilla->params->{'timetrackinggroup'})) { |