diff options
author | terry%mozilla.org <> | 2000-01-28 10:01:36 +0100 |
---|---|---|
committer | terry%mozilla.org <> | 2000-01-28 10:01:36 +0100 |
commit | 8fdb0d3601e63fb8a07bff32945fb5d84fbd4678 (patch) | |
tree | dbed4ea3cefbe7b317f3f997860e12528499eb0a /buglist.cgi | |
parent | b23cb23b54adf11260e69dbc0c6294702ea42159 (diff) | |
download | bugzilla-8fdb0d3601e63fb8a07bff32945fb5d84fbd4678.tar.gz bugzilla-8fdb0d3601e63fb8a07bff32945fb5d84fbd4678.tar.xz |
Massive stomp on the query page and buglist page. Added the ability
to use the "boolean charts" to do very powerful queries.
Diffstat (limited to 'buglist.cgi')
-rwxr-xr-x | buglist.cgi | 928 |
1 files changed, 567 insertions, 361 deletions
diff --git a/buglist.cgi b/buglist.cgi index 5cae83b87..902d09f12 100755 --- a/buglist.cgi +++ b/buglist.cgi @@ -46,17 +46,565 @@ sub sillyness { $zz = @::versions; }; - +my $serverpush = 0; ConnectToDatabase(); # print "Content-type: text/plain\n\n"; # Handy for debugging. +# $::FORM{'debug'} = 1; + + +if (grep(/^cmd-/, keys(%::FORM))) { + my $url = "query.cgi#chart?$::buffer"; + print qq{Refresh: 0; URL=$url +Content-type: text/html + +<A HREF="$url">Adding field to query page...</A> +}; + exit(); +} + + if (!defined $::FORM{'cmdtype'}) { # This can happen if there's an old bookmark to a query... $::FORM{'cmdtype'} = 'doit'; } + +sub SqlifyDate { + my ($str) = (@_); + if (!defined $str) { + $str = ""; + } + my $date = str2time($str); + if (!defined $date) { + print "\n\n<P>The string '<tt>$str</tt>' is not a legal date.\n"; + print "<P>Please click the <B>Back</B> button and try again.\n"; + PutFooter(); + exit; + } + return time2str("%Y/%m/%d %H:%M:%S", $date); +} + + +sub GetByWordList { + my ($field, $strs) = (@_); + my @list; + + foreach my $w (split(/[\s,]+/, $strs)) { + my $word = $w; + if ($word ne "") { + $word =~ tr/A-Z/a-z/; + $word = SqlQuote(quotemeta($word)); + $word =~ s/^'//; + $word =~ s/'$//; + $word = '(^|[^a-z0-9])' . $word . '($|[^a-z0-9])'; + push(@list, "lower($field) regexp '$word'"); + } + } + + return \@list; +} + + + +sub Error { + my ($str) = (@_); + if (!$serverpush) { + print "Content-type: text/html\n\n"; + } + print $str; + print "\n<P>Please press <B>Back</B> and try again.\n"; + PutFooter(); + exit(); +} + + + + + +sub GenerateSQL { + my $debug = 0; + my ($fieldsref, $supptablesref, $wherepartref, $urlstr) = (@_); + my @fields; + my @supptables; + my @wherepart; + @fields = @$fieldsref if $fieldsref; + @supptables = @$supptablesref if $supptablesref; + @wherepart = @$wherepartref if $wherepartref; + my %F; + my %M; + ParseUrlString($urlstr, \%F, \%M); + my @specialchart; + my @andlist; + + # First, deal with all the old hard-coded non-chart-based poop. + + unshift(@supptables, + ("profiles map_assigned_to", + "profiles map_reporter", + "LEFT JOIN profiles map_qa_contact ON bugs.qa_contact = map_qa_contact.userid")); + unshift(@wherepart, + ("bugs.assigned_to = map_assigned_to.userid", + "bugs.reporter = map_reporter.userid", + "bugs.groupset & $::usergroupset = bugs.groupset")); + + + my $minvotes; + if (defined $F{'votes'}) { + my $c = trim($F{'votes'}); + if ($c ne "") { + if ($c !~ /^[0-9]*$/) { + return Error("The 'At least ___ votes' field must be a\n" . + "simple number. You entered \"$c\", which\n" . + "doesn't cut it."); + } + push(@specialchart, ["votes", "greaterthan", $c - 1]); + } + } + + if ($M{'bug_id'}) { + my $type = "anyexact"; + if ($F{'bugidtype'} && $F{'bugidtype'} eq 'exclude') { + $type = "noexact"; + } + push(@specialchart, ["bug_id", $type, join(',', @{$M{'bug_id'}})]); + } + + if (defined $F{'sql'}) { + push(@wherepart, "( $F{'sql'} )"); + } + + my @legal_fields = ("product", "version", "rep_platform", "op_sys", + "bug_status", "resolution", "priority", "bug_severity", + "assigned_to", "reporter", "component", + "target_milestone", "groupset"); + + foreach my $field (keys %F) { + if (lsearch(\@legal_fields, $field) != -1) { + push(@specialchart, [$field, "anyexact", + join(',', @{$M{$field}})]); + } + } + + if ($F{'keywords'}) { + my $t = $F{'keywords_type'}; + if (!$t || $t eq "or") { + $t = "anywords"; + } + push(@specialchart, ["keywords", $t, $F{'keywords'}]); + } + + foreach my $id ("1", "2") { + if (!defined ($F{"email$id"})) { + next; + } + my $email = trim($F{"email$id"}); + if ($email eq "") { + next; + } + my $type = $F{"emailtype$id"}; + if ($type eq "exact") { + $type = "anyexact"; + foreach my $name (split(',', $email)) { + $name = trim($name); + if ($name) { + DBNameToIdAndCheck($name); + } + } + } + + my @clist; + foreach my $field ("assigned_to", "reporter", "cc", "qa_contact") { + if ($F{"email$field$id"}) { + push(@clist, $field, $type, $email); + } + } + if ($F{"emaillongdesc$id"}) { + my $table = "longdescs_"; + push(@supptables, "longdescs $table"); + push(@wherepart, "$table.bug_id = bugs.bug_id"); + my $ptable = "longdescnames_"; + push(@supptables, + "LEFT JOIN profiles $ptable ON $table.who = $ptable.userid"); + push(@clist, "$ptable.login_name", $type, $email); + } + if (@clist) { + push(@specialchart, \@clist); + } else { + return Error("You must specify one or more fields in which to\n" . + "search for <tt>$email</tt>.\n"); + } + } + + + if (defined $F{'changedin'}) { + my $c = trim($F{'changedin'}); + if ($c ne "") { + if ($c !~ /^[0-9]*$/) { + return Error("The 'changed in last ___ days' field must be\n" . + "a simple number. You entered \"$c\", which\n" . + "doesn't cut it."); + } + push(@specialchart, ["changedin", + "lessthan", $c + 1]); + } + } + + my $ref = $M{'chfield'}; + + if (defined $ref) { + my $which = lsearch($ref, "[Bug creation]"); + if ($which >= 0) { + splice(@$ref, $which, 1); + push(@specialchart, ["creation_ts", "greaterthan", + SqlifyDate($F{'chfieldfrom'})]); + my $to = $F{'chfieldto'}; + if (defined $to) { + $to = trim($to); + if ($to ne "" && $to !~ /^now$/i) { + push(@specialchart, ["creation_ts", "lessthan", + SqlifyDate($to)]); + } + } + } + } + + + + if (defined $ref && 0 < @$ref) { + push(@supptables, "bugs_activity actcheck"); + + my @list; + foreach my $f (@$ref) { + push(@list, "\nactcheck.fieldid = " . GetFieldID($f)); + } + push(@wherepart, "actcheck.bug_id = bugs.bug_id"); + push(@wherepart, "(" . join(' OR ', @list) . ")"); + push(@wherepart, "actcheck.bug_when >= " . + SqlQuote(SqlifyDate($F{'chfieldfrom'}))); + my $to = $F{'chfieldto'}; + if (defined $to) { + $to = trim($to); + if ($to ne "" && $to !~ /^now$/i) { + push(@wherepart, "actcheck.bug_when <= " . + SqlQuote(SqlifyDate($to))); + } + } + my $value = $F{'chfieldvalue'}; + if (defined $value) { + $value = trim($value); + if ($value ne "") { + push(@wherepart, "actcheck.newvalue = " . + SqlQuote($value)) + } + } + } + + + foreach my $f ("short_desc", "long_desc", "bug_file_loc", + "status_whiteboard") { + if (defined $F{$f}) { + my $s = trim($F{$f}); + if ($s ne "") { + my $n = $f; + my $q = SqlQuote($s); + my $type = $F{$f . "_type"}; + push(@specialchart, [$f, $type, $s]); + } + } + } + + + my $chartid; + my $f; + my $t; + my $q; + my $v; + my $term; + my %funcsbykey; + my @funcdefs = + ( + "^(assigned_to|reporter)," => sub { + push(@supptables, "profiles map_$f"); + push(@wherepart, "bugs.$f = map_$f.userid"); + $f = "map_$f.login_name"; + }, + "^qa_contact," => sub { + push(@supptables, + "LEFT JOIN profiles map_qa_contact ON bugs.qa_contact = map_qa_contact.userid"); + $f = "map_$f.login_name"; + }, + "^cc," => sub { + push(@supptables, + ("LEFT JOIN cc cc_$chartid ON bugs.bug_id = cc_$chartid.bug_id LEFT JOIN profiles map_cc_$chartid ON cc_$chartid.who = map_cc_$chartid.userid")); + $f = "map_cc_$chartid.login_name"; + }, + "^long_?desc,changedby" => sub { + my $table = "longdescs_$chartid"; + push(@supptables, "longdescs $table"); + push(@wherepart, "$table.bug_id = bugs.bug_id"); + my $id = DBNameToIdAndCheck($v); + $term = "$table.who = $id"; + }, + "^long_?desc,changedbefore" => sub { + my $table = "longdescs_$chartid"; + push(@supptables, "longdescs $table"); + push(@wherepart, "$table.bug_id = bugs.bug_id"); + $term = "$table.who < " . SqlQuote(SqlifyDate($v)); + }, + "^long_?desc,changedafter" => sub { + my $table = "longdescs_$chartid"; + push(@supptables, "longdescs $table"); + push(@wherepart, "$table.bug_id = bugs.bug_id"); + $term = "$table.who > " . SqlQuote(SqlifyDate($v)); + }, + "^long_?desc," => sub { + my $table = "longdescs_$chartid"; + push(@supptables, "longdescs $table"); + push(@wherepart, "$table.bug_id = bugs.bug_id"); + $f = "$table.thetext"; + }, + "^changedin," => sub { + $f = "(to_days(now()) - to_days(bugs.delta_ts))"; + }, + + "^keywords," => sub { + GetVersionTable(); + my @list; + my $table = "keywords_$chartid"; + foreach my $value (split(/[\s,]+/, $v)) { + if ($value eq '') { + next; + } + my $id = $::keywordsbyname{$value}; + if ($id) { + push(@list, "$table.keywordid = $id"); + } else { + return Error("Unknown keyword named <code>$v</code>.\n" . + "<P>The legal keyword names are\n" . + "<A HREF=describekeywords.cgi>" . + "listed here</A>.\n"); + } + } + my $haveawordterm; + if (@list) { + $haveawordterm = "(" . join(' OR ', @list) . ")"; + if ($t eq "anywords") { + $term = $haveawordterm; + } elsif ($t eq "allwords") { + $ref = $funcsbykey{",$t"}; + &$ref; + if ($term && $haveawordterm) { + $term = "(($term) AND $haveawordterm)"; + } + } + } + if ($term) { + push(@supptables, "keywords $table"); + push(@wherepart, "$table.bug_id = bugs.bug_id"); + } + }, + + + ",equals" => sub { + $term = "$f = $q"; + }, + ",notequals" => sub { + $term = "$f != $q"; + }, + ",casesubstring" => sub { + $term = "INSTR($f, $q)"; + }, + ",(substring|substr)" => sub { + $term = "INSTR(LOWER($f), " . lc($q) . ")"; + }, + ",notsubstring" => sub { + $term = "INSTR(LOWER($f), " . lc($q) . ") = 0"; + }, + ",regexp" => sub { + $term = "LOWER($f) REGEXP $q"; + }, + ",notregexp" => sub { + $term = "LOWER($f) NOT REGEXP $q"; + }, + ",lessthan" => sub { + $term = "$f < $q"; + }, + ",greaterthan" => sub { + $term = "$f > $q"; + }, + ",anyexact" => sub { + my @list; + foreach my $w (split(/,/, $v)) { + if ($w eq "---") { + $w = ""; + } + push(@list, "$f = " . SqlQuote($w)); + } + $term = join(" OR ", @list); + }, + ",anywords" => sub { + $term = join(" OR ", @{GetByWordList($f, $v)}); + }, + ",allwords" => sub { + $term = join(" AND ", @{GetByWordList($f, $v)}); + }, + ",nowords" => sub { + my @list = @{GetByWordList($f, $v)}; + if (@list) { + $term = "NOT (" . join(" OR ", @list) . ")"; + } + }, + ",changedbefore" => sub { + my $table = "act_$chartid"; + my $ftable = "fielddefs_$chartid"; + push(@supptables, "bugs_activity $table"); + push(@supptables, "fielddefs $ftable"); + push(@wherepart, "$table.bug_id = bugs.bug_id"); + push(@wherepart, "$table.fieldid = $ftable.fieldid"); + $term = "($ftable.name = '$f' AND $table.bug_when < $q)"; + }, + ",changedafter" => sub { + my $table = "act_$chartid"; + my $ftable = "fielddefs_$chartid"; + push(@supptables, "bugs_activity $table"); + push(@supptables, "fielddefs $ftable"); + push(@wherepart, "$table.bug_id = bugs.bug_id"); + push(@wherepart, "$table.fieldid = $ftable.fieldid"); + $term = "($ftable.name = '$f' AND $table.bug_when > $q)"; + }, + ",changedto" => sub { + my $table = "act_$chartid"; + my $ftable = "fielddefs_$chartid"; + push(@supptables, "bugs_activity $table"); + push(@supptables, "fielddefs $ftable"); + push(@wherepart, "$table.bug_id = bugs.bug_id"); + push(@wherepart, "$table.fieldid = $ftable.fieldid"); + $term = "($ftable.name = '$f' AND $table.newvalue = $q)"; + }, + ",changedby" => sub { + my $table = "act_$chartid"; + my $ftable = "fielddefs_$chartid"; + push(@supptables, "bugs_activity $table"); + push(@supptables, "fielddefs $ftable"); + push(@wherepart, "$table.bug_id = bugs.bug_id"); + push(@wherepart, "$table.fieldid = $ftable.fieldid"); + my $id = DBNameToIdAndCheck($v); + $term = "($ftable.name = '$f' AND $table.who = $id)"; + }, + ); + my @funcnames; + while (@funcdefs) { + my $key = shift(@funcdefs); + my $value = shift(@funcdefs); + if ($key =~ /^[^,]*$/) { + die "All defs in %funcs must have a comma in their name: $key"; + } + if (exists $funcsbykey{$key}) { + die "Duplicate key in %funcs: $key"; + } + $funcsbykey{$key} = $value; + push(@funcnames, $key); + } + + + my $chart = -1; + my $row = 0; + foreach my $ref (@specialchart) { + my $col = 0; + while (@$ref) { + $F{"field$chart-$row-$col"} = shift(@$ref); + $F{"type$chart-$row-$col"} = shift(@$ref); + $F{"value$chart-$row-$col"} = shift(@$ref); + if ($debug) { + print qq{<P>$F{"field$chart-$row-$col"} | $F{"type$chart-$row-$col"} | $F{"value$chart-$row-$col"}*\n}; + } + $col++; + + } + $row++; + } + + + for ($chart=-1 ; + $chart < 0 || exists $F{"field$chart-0-0"} ; + $chart++) { + $chartid = $chart >= 0 ? $chart : ""; + for (my $row = 0 ; + exists $F{"field$chart-$row-0"} ; + $row++) { + my @orlist; + for (my $col = 0 ; + exists $F{"field$chart-$row-$col"} ; + $col++) { + $f = $F{"field$chart-$row-$col"} || "noop"; + $t = $F{"type$chart-$row-$col"} || "noop"; + $v = $F{"value$chart-$row-$col"}; + $v = "" if !defined $v; + $v = trim($v); + if ($f eq "noop" || $t eq "noop" || $v eq "") { + next; + } + $q = SqlQuote($v); + my $func; + $term = undef; + foreach my $key (@funcnames) { + if ("$f,$t" =~ m/$key/) { + my $ref = $funcsbykey{$key}; + if ($debug) { + print "<P>$key ($f , $t ) => "; + } + &$ref; + if ($debug) { + print "$f , $t , $term"; + } + if ($term) { + last; + } + } + } + if ($term) { + push(@orlist, $term); + } else { + my $errstr = "Can't seem to handle " . + qq{'<code>$F{"field$chart-$row-$col"}</code>' and } . + qq{'<code>$F{"type$chart-$row-$col"}</code>' } . + "together"; + die "Internal error: $errstr" if $chart < 0; + return Error($errstr); + } + } + if (@orlist) { + push(@andlist, "(" . join(" OR ", @orlist) . ")"); + } + } + } + my %suppseen = ("bugs" => 1); + my $suppstring = "bugs"; + foreach my $str (@supptables) { + if (!$suppseen{$str}) { + if ($str !~ /^LEFT JOIN/i) { + $suppstring .= ","; + } + $suppstring .= " $str"; + $suppseen{$str} = 1; + } + } + my $query = ("SELECT " . join(', ', @fields) . + " FROM $suppstring" . + " WHERE " . join(' AND ', (@wherepart, @andlist)) . + " GROUP BY bugs.bug_id"); + if ($debug) { + print "<P><CODE>" . value_quote($query) . "</CODE><P>\n"; + exit(); + } + return $query; +} + + + sub LookupNamedQuery { my ($name) = (@_); confirm_login(); @@ -164,7 +712,6 @@ OK, you have a new query named <code>$name</code> } -my $serverpush = 0; if ($ENV{'HTTP_USER_AGENT'} =~ /Mozilla.[3-9]/ && $ENV{'HTTP_USER_AGENT'} !~ /[Cc]ompatible/ ) { # Search for real Netscape 3 and up. http://www.browsercaps.org used as source of # browsers compatbile with server-push. It's a Netscape hack, incompatbile @@ -205,9 +752,11 @@ DefCol("severity", "substring(bugs.bug_severity, 1, 3)", "Sev", DefCol("priority", "substring(bugs.priority, 1, 3)", "Pri", "bugs.priority"); DefCol("platform", "substring(bugs.rep_platform, 1, 3)", "Plt", "bugs.rep_platform"); -DefCol("owner", "assign.login_name", "Owner", "assign.login_name"); -DefCol("reporter", "report.login_name", "Reporter", "report.login_name"); -DefCol("qa_contact", "qacont.login_name", "QAContact", "qacont.login_name"); +DefCol("owner", "map_assigned_to.login_name", "Owner", + "map_assigned_to.login_name"); +DefCol("reporter", "map_reporter.login_name", "Reporter", + "map_reporter.login_name"); +DefCol("qa_contact", "map_qa_contact.login_name", "QAContact", "map_qa_contact.login_name"); DefCol("status", "substring(bugs.bug_status,1,4)", "State", "bugs.bug_status"); DefCol("resolution", "substring(bugs.resolution,1,4)", "Result", "bugs.resolution"); @@ -233,16 +782,7 @@ if (defined $::COOKIE{'COLUMNLIST'}) { my $minvotes; if (defined $::FORM{'votes'}) { - my $c = trim($::FORM{'votes'}); - if ($c ne "") { - if ($c !~ /^[0-9]*$/) { - print "\n\n<P>The 'At least ___ votes' field must be a simple "; - print "number. You entered \"$c\", which doesn't cut it."; - print "<P>Please click the <B>Back</B> button and try again.\n"; - PutFooter(); - exit; - } - $minvotes = $c; + if (trim($::FORM{'votes'}) ne "") { if (! (grep {/^votes$/} @collist)) { push(@collist, 'votes'); } @@ -259,36 +799,20 @@ if ($dotweak) { } -my $query = "select bugs.bug_id, bugs.groupset"; +my @fields = ("bugs.bug_id", "bugs.groupset"); foreach my $c (@collist) { if (exists $::needquote{$c}) { - $query .= ", -\t$::key{$c}"; + push(@fields, "$::key{$c}"); } } if ($dotweak) { - $query .= ", -bugs.product, -bugs.bug_status"; + push(@fields, "bugs.product", "bugs.bug_status"); } -$query .= " -from bugs, - profiles assign, - profiles report - left join profiles qacont on bugs.qa_contact = qacont.userid, - versions projector - -where bugs.assigned_to = assign.userid -and bugs.reporter = report.userid -and bugs.product = projector.program -and bugs.version = projector.value -and bugs.groupset & $::usergroupset = bugs.groupset -"; if ($::FORM{'regetlastlist'}) { if (!$::COOKIE{'BUGLIST'}) { @@ -309,331 +833,10 @@ query. You will have to start over at the <A HREF="query.cgi">query page</A>. url_quote($::FORM{'order'}); } -if ((defined $::FORM{'emailcc1'} && $::FORM{'emailcc1'}) || - (defined $::FORM{'emailcc2'} && $::FORM{'emailcc2'})) { - - # We need to poke into the CC table. Do weird SQL left join stuff so that - # we can look in the CC table, but won't reject any bugs that don't have - # any CC fields. - $query =~ s/bugs,/bugs left join cc on bugs.bug_id = cc.bug_id left join profiles ccname on cc.who = ccname.userid,/; -} - -my $needlongdescs = 0; # Whether we need to patch in the longdescs - # table. - - -if ($::MFORM{'bug_id'}) { - my @list = grep(!/^$/, split(/[^0-9]+/, join(',', @{$::MFORM{'bug_id'}}))); - if (@list) { - my $verb = "IN"; - if ($::FORM{'bugidtype'} && $::FORM{'bugidtype'} eq 'exclude') { - $verb = "NOT IN"; - } - $query .= " AND bugs.bug_id $verb (" . join(',', @list) . ") "; - } -} - - - -if (defined $::FORM{'sql'}) { - $query .= "and (\n$::FORM{'sql'}\n)" -} else { - my @legal_fields = ("product", "version", "rep_platform", "op_sys", - "bug_status", "resolution", "priority", "bug_severity", - "assigned_to", "reporter", "component", - "target_milestone", "groupset"); - - foreach my $field (keys %::FORM) { - my $or = ""; - if (lsearch(\@legal_fields, $field) != -1 && $::FORM{$field} ne "") { - $query .= "\tand (\n"; - if ($field eq "assigned_to" || $field eq "reporter") { - foreach my $p (split(/,/, $::FORM{$field})) { - my $whoid = DBNameToIdAndCheck($p); - $query .= "\t\t${or}bugs.$field = $whoid\n"; - $or = "or "; - } - } else { - my $ref = $::MFORM{$field}; - foreach my $v (@$ref) { - if ($v eq "(empty)") { - $query .= "\t\t${or}bugs.$field is null\n"; - } else { - if ($v eq "---") { - $query .= "\t\t${or}bugs.$field = ''\n"; - } else { - $query .= "\t\t${or}bugs.$field = " . SqlQuote($v) . - "\n"; - } - } - $or = "or "; - } - } - $query .= "\t)\n"; - } - } -} - -if ($::FORM{'keywords'}) { - GetVersionTable(); - my @list; - foreach my $v (split(/[\s,]+/, $::FORM{'keywords'})) { - if ($v eq '') { - next; - } - my $id = $::keywordsbyname{$v}; - if ($id) { - push(@list, "keywords.keywordid = $id"); - } else { - print "Unknown keyword named <code>$v</code>.\n"; - print "<P>The legal keyword names are <A HREF=describekeywords.cgi>"; - print "listed here</A>.\n"; - print "<P>Please click the <B>Back</B> button and try again.\n"; - PutFooter(); - exit; - } - } - if (@list) { - $query =~ s/where/, keywords where/; - my $type = $::FORM{'keywords_type'}; - my $notopt = ""; - if ($type eq "nowords") { - # Ought to take advantage of keyword table somehow! ### - my $extra = GetByWordList("bugs.keywords", $::FORM{'keywords'}, - "or"); - $extra =~ s/AND/AND NOT/i; - $query .= $extra; - } else { - $query .= "and keywords.bug_id = bugs.bug_id and $notopt (" . - join(" or ", @list) . ")\n"; - if ($type eq "allwords") { - # This needs to be tuned to take better advantage of the - # keyword table! - $query .= GetByWordList("bugs.keywords", $::FORM{'keywords'}, - "and"); - } - } - } -} - - -foreach my $id ("1", "2") { - if (!defined ($::FORM{"email$id"})) { - next; - } - my $email = trim($::FORM{"email$id"}); - if ($email eq "") { - next; - } - my $qemail = SqlQuote($email); - my $type = $::FORM{"emailtype$id"}; - my $emailid; - if ($type eq "exact") { - $emailid = DBNameToIdAndCheck($email); - } - - my $foundone = 0; - my $lead= "and (\n"; - foreach my $field ("assigned_to", "reporter", "cc", "qa_contact", - "longdesc") { - my $doit = $::FORM{"email$field$id"}; - if (!$doit) { - next; - } - $foundone = 1; - my $table; - if ($field eq "assigned_to") { - $table = "assign"; - } elsif ($field eq "reporter") { - $table = "report"; - } elsif ($field eq "qa_contact") { - $table = "qacont"; - } elsif ($field eq "longdesc") { - $table = "longdescname"; - $needlongdescs = 1; - } else { - $table = "ccname"; - } - if ($type eq "exact") { - if ($field eq "cc") { - $query .= "\t$lead cc.who = $emailid\n"; - } elsif ($field eq "longdesc") { - $query .= "\t$lead longdescs.who = $emailid\n"; - } else { - $query .= "\t$lead $field = $emailid\n"; - } - } elsif ($type eq "regexp") { - $query .= "\t$lead $table.login_name regexp $qemail\n"; - } elsif ($type eq "notregexp") { - $query .= "\t$lead $table.login_name not regexp $qemail\n"; - } else { - $query .= "\t$lead instr($table.login_name, $qemail)\n"; - } - $lead = " or "; - } - if (!$foundone) { - print "\n\n<P>You must specify one or more fields in which to search for <tt>$email</tt>.\n"; - print "<P>Please click the <B>Back</B> button and try again.\n"; - PutFooter(); - exit; - } - if ($lead eq " or ") { - $query .= ")\n"; - } -} - - +my $query = GenerateSQL(\@fields, undef, undef, $::buffer); -if (defined $::FORM{'changedin'}) { - my $c = trim($::FORM{'changedin'}); - if ($c ne "") { - if ($c !~ /^[0-9]*$/) { - print "\n\n<P>The 'changed in last ___ days' field must be a simple "; - print "number. You entered \"$c\", which doesn't cut it."; - print "<P>Please click the <B>Back</B> button and try again.\n"; - PutFooter(); - exit; - } - $query .= "and to_days(now()) - to_days(bugs.delta_ts) <= $c "; - } -} - -if (defined $minvotes) { - $query .= "and votes >= $minvotes "; -} - - -my $ref = $::MFORM{'chfield'}; - - -sub SqlifyDate { - my ($str) = (@_); - if (!defined $str) { - $str = ""; - } - my $date = str2time($str); - if (!defined $date) { - print "\n\n<P>The string '<tt>$str</tt>' is not a legal date.\n"; - print "<P>Please click the <B>Back</B> button and try again.\n"; - PutFooter(); - exit; - } - return time2str("'%Y/%m/%d %H:%M:%S'", $date); -} - - -if (defined $ref) { - my $which = lsearch($ref, "[Bug creation]"); - if ($which >= 0) { - splice(@$ref, $which, 1); - $query .= "and bugs.creation_ts >= " . - SqlifyDate($::FORM{'chfieldfrom'}) . "\n"; - my $to = $::FORM{'chfieldto'}; - if (defined $to) { - $to = trim($to); - if ($to ne "" && $to !~ /^now$/i) { - $query .= "and bugs.creation_ts <= " . - SqlifyDate($to) . "\n"; - } - } - } -} - - - -if (defined $ref && 0 < @$ref) { - # Do surgery on the query to tell it to patch in the bugs_activity - # table. - $query =~ s/where/, bugs_activity where/; - - my @list; - foreach my $f (@$ref) { - push(@list, "\nbugs_activity.fieldid = " . GetFieldID($f)); - } - $query .= "and bugs_activity.bug_id = bugs.bug_id and (" . - join(' or ', @list) . ") "; - $query .= "and bugs_activity.bug_when >= " . - SqlifyDate($::FORM{'chfieldfrom'}) . "\n"; - my $to = $::FORM{'chfieldto'}; - if (defined $to) { - $to = trim($to); - if ($to ne "" && $to !~ /^now$/i) { - $query .= "and bugs_activity.bug_when <= " . SqlifyDate($to) . "\n"; - } - } - my $value = $::FORM{'chfieldvalue'}; - if (defined $value) { - $value = trim($value); - if ($value ne "") { - $query .= "and bugs_activity.newvalue = " . - SqlQuote($value) . "\n"; - } - } -} - -sub GetByWordList { - my ($field, $strs, $verb) = (@_); - my @list; - - foreach my $w (split(/[\s,]+/, $strs)) { - my $word = $w; - if ($word ne "") { - $word =~ tr/A-Z/a-z/; - $word = SqlQuote(quotemeta($word)); - $word =~ s/^'//; - $word =~ s/'$//; - $word = '(^|[^a-z0-9])' . $word . '($|[^a-z0-9])'; - push(@list, "lower($field) regexp '$word'"); - } - } - - if (0 == @list) { - return ""; - } - - return "and (" . join(" $verb ", @list) . ")\n"; -} - -foreach my $f ("short_desc", "long_desc", "bug_file_loc", - "status_whiteboard") { - if (defined $::FORM{$f}) { - my $s = trim($::FORM{$f}); - if ($s ne "") { - my $n = $f; - my $q = SqlQuote($s); - my $type = $::FORM{$f . "_type"}; - if ($f eq "long_desc") { - $needlongdescs = 1; # Patch in the longdescs table. - $query .= "and longdescs.bug_id = bugs.bug_id\n"; - $n = "longdescs.thetext"; - } - if ($type eq "regexp") { - $query .= "and $n regexp $q\n"; - } elsif ($type eq "notregexp") { - $query .= "and $n not regexp $q\n"; - } elsif ($type eq "casesubstring") { - $query .= "and instr($n, $q)\n"; - } elsif ($type eq "allwords") { - $query .= GetByWordList($n, $s, "and"); - } elsif ($type eq "anywords") { - $query .= GetByWordList($n, $s, "or"); - } else { - $query .= "and instr(lower($n), lower($q))\n"; - } - } - } -} - -if ($needlongdescs) { - $query =~ s/where/, longdescs left join profiles longdescname on longdescs.who = longdescname.userid where/; - $query .= " AND longdescs.bug_id = bugs.bug_id "; -} - - - -$query .= "group by bugs.bug_id\n"; if ($::COOKIE{'LASTORDER'}) { @@ -644,9 +847,12 @@ if ($::COOKIE{'LASTORDER'}) { if (defined $::FORM{'order'} && $::FORM{'order'} ne "") { - $query .= "order by "; + $query .= " ORDER BY "; $::FORM{'order'} =~ s/votesum/bugs.votes/; # Silly backwards compatability # hack. + $::FORM{'order'} =~ s/assign\.login_name/map_assigned_to.login_name/g; + # Another backwards compatability hack. + ORDER: for ($::FORM{'order'}) { /\./ && do { # This (hopefully) already has fieldnames in it, so we're done. @@ -661,18 +867,18 @@ if (defined $::FORM{'order'} && $::FORM{'order'} ne "") { last ORDER; }; /Assign/ && do { - $::FORM{'order'} = "assign.login_name, bugs.bug_status, priority, bugs.bug_id"; + $::FORM{'order'} = "map_assigned_to.login_name, bugs.bug_status, priority, bugs.bug_id"; last ORDER; }; # DEFAULT - $::FORM{'order'} = "bugs.bug_status, bugs.priority, assign.login_name, bugs.bug_id"; + $::FORM{'order'} = "bugs.bug_status, bugs.priority, map_assigned_to.login_name, bugs.bug_id"; } $query .= $::FORM{'order'}; } if ($::FORM{'debug'} && $serverpush) { - print "<PRE>$query</PRE>\n"; + print "<P><CODE>" . value_quote($query) . "</CODE><P>\n"; } @@ -866,7 +1072,7 @@ print " <B>" . time2str("%a %b %e %T %Z %Y", time()) . "</B>"; if (defined $::FORM{'debug'}) { - print "<PRE>$query</PRE>\n"; + print "<P><CODE>" . value_quote($query) . "</CODE><P>\n"; } if ($toolong) { |