From 8fdb0d3601e63fb8a07bff32945fb5d84fbd4678 Mon Sep 17 00:00:00 2001 From: "terry%mozilla.org" <> Date: Fri, 28 Jan 2000 09:01:36 +0000 Subject: Massive stomp on the query page and buglist page. Added the ability to use the "boolean charts" to do very powerful queries. --- buglist.cgi | 928 +++++++++++++++++++++++++++++++++++++----------------------- 1 file changed, 567 insertions(+), 361 deletions(-) (limited to 'buglist.cgi') 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 + +Adding field to query page... +}; + 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
The string '$str' is not a legal date.\n"; + print "
Please click the Back 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
Please press Back 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 $email.\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 $v
.\n" .
+ "
The legal keyword names are\n" . + "" . + "listed here.\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{
$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 "
$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{'$F{"field$chart-$row-$col"}
' and } .
+ qq{'$F{"type$chart-$row-$col"}
' } .
+ "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 "
" . value_quote($query) . "
\n";
+ exit();
+ }
+ return $query;
+}
+
+
+
sub LookupNamedQuery {
my ($name) = (@_);
confirm_login();
@@ -164,7 +712,6 @@ OK, you have a new query named $name
}
-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
The 'At least ___ votes' field must be a simple "; - print "number. You entered \"$c\", which doesn't cut it."; - print "
Please click the Back 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 query page.
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 $v
.\n";
- print "
The legal keyword names are "; - print "listed here.\n"; - print "
Please click the Back 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
You must specify one or more fields in which to search for $email.\n"; - print "
Please click the Back 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
The 'changed in last ___ days' field must be a simple "; - print "number. You entered \"$c\", which doesn't cut it."; - print "
Please click the Back 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
The string '$str' is not a legal date.\n"; - print "
Please click the Back 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 "
$query\n"; + print "
" . value_quote($query) . "
\n"; } @@ -866,7 +1072,7 @@ print " " . time2str("%a %b %e %T %Z %Y", time()) . ""; if (defined $::FORM{'debug'}) { - print "
$query\n"; + print "
" . value_quote($query) . "
\n"; } if ($toolong) { -- cgit v1.2.3-24-g4f1b