Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
bugzilla
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
etersoft
bugzilla
Commits
daa533e7
You need to sign in or sign up before continuing.
Commit
daa533e7
authored
Oct 04, 2010
by
Max Kanat-Alexander
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Bug 601848: Fix percentage_complete searches for all operators on both MySQL
and PostgreSQL r=mkanat, a=mkanat (module owner)
parent
e861a6de
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
80 additions
and
88 deletions
+80
-88
Bug.pm
Bugzilla/Bug.pm
+4
-1
Search.pm
Bugzilla/Search.pm
+20
-36
Constants.pm
xt/lib/Bugzilla/Test/Search/Constants.pm
+53
-45
FieldTest.pm
xt/lib/Bugzilla/Test/Search/FieldTest.pm
+3
-6
No files found.
Bugzilla/Bug.pm
View file @
daa533e7
...
...
@@ -3327,7 +3327,10 @@ sub percentage_complete {
my
$actual
=
$self
->
actual_time
;
my
$total
=
$remaining
+
$actual
;
return
undef
if
$total
==
0
;
return
100
*
(
$actual
/
$total
);
# Search.pm truncates this value to an integer, so we want to as well,
# since this is mostly used in a test where its value needs to be
# identical to what the database will return.
return
int
(
100
*
(
$actual
/
$total
));
}
sub
product
{
...
...
Bugzilla/Search.pm
View file @
daa533e7
...
...
@@ -406,6 +406,11 @@ use constant COLUMN_DEPENDS => {
# DB::Schema to figure out what needs to be joined, but for some
# fields it needs a little help.
use
constant
COLUMN_JOINS
=>
{
actual_time
=>
{
table
=>
'(SELECT bug_id, SUM(work_time) AS total'
.
' FROM longdescs GROUP BY bug_id)'
,
join
=>
'INNER'
,
},
assigned_to
=>
{
from
=>
'assigned_to'
,
to
=>
'userid'
,
...
...
@@ -441,10 +446,6 @@ use constant COLUMN_JOINS => {
to
=>
'id'
,
join
=>
'INNER'
,
},
actual_time
=>
{
table
=>
'longdescs'
,
join
=>
'INNER'
,
},
'flagtypes.name'
=>
{
as
=>
'map_flags'
,
table
=>
'flags'
,
...
...
@@ -504,18 +505,20 @@ sub COLUMNS {
# Next we define columns that have special SQL instead of just something
# like "bugs.bug_id".
my
$actual_time
=
'(SUM(map_actual_time.work_time)'
.
' * COUNT(DISTINCT map_actual_time.bug_when)/COUNT(bugs.bug_id))'
;
my
$total_time
=
"(map_actual_time.total + bugs.remaining_time)"
;
my
%
special_sql
=
(
deadline
=>
$dbh
->
sql_date_format
(
'bugs.deadline'
,
'%Y-%m-%d'
),
actual_time
=>
$actual_time
,
actual_time
=>
'map_actual_time.total'
,
# "FLOOR" is in there to turn this into an integer, making searches
# totally predictable. Otherwise you get floating-point numbers that
# are rather hard to search reliably if you're asking for exact
# numbers.
percentage_complete
=>
"(CASE WHEN $actual_time + bugs.remaining_time = 0.0"
.
" THEN 0.0"
.
" ELSE 100"
.
" * ($actual_time / ($actual_time + bugs.remaining_time))"
.
" END)"
,
"(CASE WHEN $total_time = 0"
.
" THEN 0"
.
" ELSE FLOOR(100 * (map_actual_time.total / $total_time))"
.
" END)"
,
'flagtypes.name'
=>
$dbh
->
sql_group_concat
(
'DISTINCT '
.
$dbh
->
sql_string_concat
(
'map_flagtypes.name'
,
'map_flags.status'
)),
...
...
@@ -614,7 +617,6 @@ sub REPORT_COLUMNS {
# 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
...
...
@@ -2240,30 +2242,12 @@ sub _work_time {
sub
_percentage_complete
{
my
(
$self
,
$args
)
=
@_
;
my
(
$chart_id
,
$joins
,
$operator
,
$having
,
$fields
)
=
@$args
{
qw(chart_id joins operator having fields)
};
my
$table
=
"longdescs_$chart_id"
;
# We can't just use "percentage_complete" as the field, because
# (a) PostgreSQL doesn't accept it in the HAVING clause
# and (b) it wouldn't work in multiple chart rows, because it uses
# a fixed name for the table, "ldtime".
my
$expression
=
COLUMNS
->
{
percentage_complete
}
->
{
name
};
$expression
=~
s/\bldtime\b/$table/g
;
$args
->
{
full_field
}
=
"($expression)"
;
push
(
@$joins
,
{
table
=>
'longdescs'
,
as
=>
$table
});
# We need remaining_time in _select_columns, otherwise we can't use
# it in the expression for creating percentage_complete.
$self
->
_add_extra_column
(
'remaining_time'
);
$args
->
{
full_field
}
=
COLUMNS
->
{
percentage_complete
}
->
{
name
};
$self
->
_do_operator_function
(
$args
);
push
(
@$having
,
$args
->
{
term
});
# We put something into $args->{term} so that do_search_function
# stops processing.
$args
->
{
term
}
=
''
;
# We need actual_time in _select_columns, otherwise we can't use
# it in the expression for searching percentage_complete.
$self
->
_add_extra_column
(
'actual_time'
);
}
sub
_bug_group_nonchanged
{
...
...
xt/lib/Bugzilla/Test/Search/Constants.pm
View file @
daa533e7
...
...
@@ -140,7 +140,6 @@ use constant SKIP_FIELDS => qw(
# right in OR tests, and it's too much work to document the exact tests
# that they cause to fail.
use
constant
OR_SKIP
=>
qw(
percentage_complete
flagtypes.name
)
;
...
...
@@ -167,7 +166,7 @@ use constant FIELD_SUBSTR_SIZE => {
deadline
=>
-
5
,
creation_ts
=>
-
8
,
delta_ts
=>
-
8
,
percentage_complete
=>
7
,
percentage_complete
=>
1
,
work_time
=>
3
,
remaining_time
=>
3
,
target_milestone
=>
15
,
...
...
@@ -361,19 +360,8 @@ use constant KNOWN_BROKEN => {
work_time
=>
{
contains
=>
[
2
,
3
,
4
]
},
},
greaterthan
=>
{
GREATERTHAN_BROKEN
},
# percentage_complete is broken -- it won't match equal values.
greaterthaneq
=>
{
GREATERTHAN_BROKEN
,
percentage_complete
=>
{
contains
=>
[
2
]
},
},
# percentage_complete doesn't do a numeric comparison, so
# it doesn't find decimal values.
anyexact
=>
{
percentage_complete
=>
{
contains
=>
[
2
]
},
},
greaterthan
=>
{
GREATERTHAN_BROKEN
},
greaterthaneq
=>
{
GREATERTHAN_BROKEN
},
'allwordssubstr-<1>'
=>
{
ALLWORDS_BROKEN
},
# flagtypes.name does not work here, probably because they all try to
...
...
@@ -399,7 +387,6 @@ use constant KNOWN_BROKEN => {
work_time
=>
{
contains
=>
[
1
]
},
},
'anywords-<1> <2>'
=>
{
percentage_complete
=>
{
contains
=>
[
2
]
},
work_time
=>
{
contains
=>
[
1
,
2
]
},
},
...
...
@@ -481,16 +468,6 @@ use constant PG_BROKEN => {
notregexp
=>
{
contains
=>
[
5
]
},
nowords
=>
{
contains
=>
[
5
]
},
},
percentage_complete
=>
{
'allwordssubstr-<1>'
=>
{
contains
=>
[
3
]
},
anywordssubstr
=>
{
contains
=>
[
2
,
3
]
},
casesubstring
=>
{
contains
=>
[
3
]
},
'notregexp-<1>'
=>
{
contains
=>
[
3
]
},
notsubstring
=>
{
contains
=>
[
3
]
},
nowordssubstr
=>
{
contains
=>
[
3
]
},
'regexp-<1>'
=>
{
contains
=>
[
3
]
},
substring
=>
{
contains
=>
[
3
]
},
},
};
###################
...
...
@@ -512,7 +489,6 @@ use constant COMMON_BROKEN_NOT => (
"flagtypes.name"
=>
{
contains
=>
[
5
]
},
"keywords"
=>
{
contains
=>
[
5
]
},
"longdescs.isprivate"
=>
{
contains
=>
[
1
]
},
"percentage_complete"
=>
{
contains
=>
[
1
..
5
]
},
"see_also"
=>
{
contains
=>
[
5
]
},
FIELD_TYPE_BUG_ID
,
{
contains
=>
[
5
]
},
FIELD_TYPE_DATETIME
,
{
contains
=>
[
5
]
},
...
...
@@ -527,7 +503,7 @@ use constant CHANGED_BROKEN_NOT => (
"classification"
=>
{
contains
=>
[
1
]
},
"commenter"
=>
{
contains
=>
[
1
]
},
"delta_ts"
=>
{
contains
=>
[
1
]
},
"percentage_complete"
=>
{
contains
=>
[
1
]
},
percentage_complete
=>
{
contains
=>
[
1
]
},
"requestees.login_name"
=>
{
contains
=>
[
1
]
},
"setters.login_name"
=>
{
contains
=>
[
1
]
},
"work_time"
=>
{
contains
=>
[
1
]
},
...
...
@@ -549,7 +525,6 @@ use constant NEGATIVE_BROKEN_NOT => (
"bug_group"
=>
{
contains
=>
[
5
]
},
"dependson"
=>
{
contains
=>
[
2
,
4
,
5
]
},
"flagtypes.name"
=>
{
contains
=>
[
1
..
5
]
},
"percentage_complete"
=>
{
contains
=>
[
1
..
5
]
},
);
# These are field/operator combinations that are broken when run under NOT().
...
...
@@ -603,7 +578,6 @@ use constant BROKEN_NOT => {
},
'anyexact-<1>, <2>'
=>
{
bug_group
=>
{
contains
=>
[
1
]
},
percentage_complete
=>
{
contains
=>
[
1
,
3
,
4
,
5
]
},
keywords
=>
{
contains
=>
[
1
,
5
]
},
see_also
=>
{
},
FIELD_TYPE_MULTI_SELECT
,
{
},
...
...
@@ -616,7 +590,6 @@ use constant BROKEN_NOT => {
},
'anywords-<1> <2>'
=>
{
'attach_data.thedata'
=>
{
contains
=>
[
5
]
},
"percentage_complete"
=>
{
contains
=>
[
1
,
3
,
4
,
5
]
},
work_time
=>
{
contains
=>
[
1
,
2
]
},
},
anywordssubstr
=>
{
...
...
@@ -624,7 +597,6 @@ use constant BROKEN_NOT => {
"work_time"
=>
{
contains
=>
[
1
,
2
]
},
},
'anywordssubstr-<1> <2>'
=>
{
percentage_complete
=>
{
contains
=>
[
1
,
2
,
3
,
4
,
5
]
},
FIELD_TYPE_MULTI_SELECT
,
{
contains
=>
[
5
]
},
},
casesubstring
=>
{
...
...
@@ -645,8 +617,8 @@ use constant BROKEN_NOT => {
"attach_data.thedata"
=>
{
contains
=>
[
2
,
3
,
4
]
},
"classification"
=>
{
contains
=>
[
2
,
3
,
4
]
},
"commenter"
=>
{
contains
=>
[
2
,
3
,
4
]
},
percentage_complete
=>
{
contains
=>
[
2
,
3
,
4
]
},
"delta_ts"
=>
{
contains
=>
[
2
,
3
,
4
]
},
"percentage_complete"
=>
{
contains
=>
[
2
,
3
,
4
]
},
"requestees.login_name"
=>
{
contains
=>
[
2
,
3
,
4
]
},
"setters.login_name"
=>
{
contains
=>
[
2
,
3
,
4
]
},
},
...
...
@@ -693,7 +665,6 @@ use constant BROKEN_NOT => {
cc
=>
{
contains
=>
[
1
]
},
"flagtypes.name"
=>
{
contains
=>
[
2
,
5
]
},
"work_time"
=>
{
contains
=>
[
2
,
3
,
4
]
},
percentage_complete
=>
{
contains
=>
[
1
,
3
,
4
,
5
]
},,
FIELD_TYPE_MULTI_SELECT
,
{
contains
=>
[
5
]
},
},
lessthan
=>
{
...
...
@@ -717,14 +688,14 @@ use constant BROKEN_NOT => {
notsubstring
=>
{
NEGATIVE_BROKEN_NOT
},
nowords
=>
{
NEGATIVE_BROKEN_NOT
,
"work_time"
=>
{
contains
=>
[
2
,
3
,
4
]
},
"work_time"
=>
{
contains
=>
[
2
,
3
,
4
]
},
"flagtypes.name"
=>
{
},
},
nowordssubstr
=>
{
NEGATIVE_BROKEN_NOT
,
"attach_data.thedata"
=>
{
},
"flagtypes.name"
=>
{
},
"work_time"
=>
{
contains
=>
[
2
,
3
,
4
]
},
"work_time"
=>
{
contains
=>
[
2
,
3
,
4
]
},
},
regexp
=>
{
COMMON_BROKEN_NOT
,
...
...
@@ -774,7 +745,7 @@ use constant REGEX_OVERRIDE => {
remaining_time
=>
{
value
=>
'^9.0'
},
work_time
=>
{
value
=>
'^1.0'
},
longdesc
=>
{
value
=>
'^1-'
},
percentage_complete
=>
{
value
=>
'^10
.0
'
},
percentage_complete
=>
{
value
=>
'^10'
},
FIELD_TYPE_BUG_ID
,
{
value
=>
'^<1>$'
},
FIELD_TYPE_DATETIME
,
{
value
=>
'^2037-03-01'
}
};
...
...
@@ -915,22 +886,46 @@ use constant TESTS => {
{
contains
=>
[
2
,
3
,
4
,
5
],
value
=>
'<1>'
},
],
substring
=>
[
{
contains
=>
[
1
],
value
=>
'<1>'
},
{
contains
=>
[
1
],
value
=>
'<1>'
,
override
=>
{
percentage_complete
=>
{
contains
=>
[
1
,
2
,
3
]
},
}
},
],
casesubstring
=>
[
{
contains
=>
[
1
],
value
=>
'<1>'
},
{
contains
=>
[
1
],
value
=>
'<1>'
,
override
=>
{
percentage_complete
=>
{
contains
=>
[
1
,
2
,
3
]
},
}
},
{
contains
=>
[]
,
value
=>
'<1>'
,
transform
=>
sub
{
lc
(
$_
[
0
])
},
extra_name
=>
'lc'
,
if_equal
=>
{
contains
=>
[
1
]
}
},
extra_name
=>
'lc'
,
if_equal
=>
{
contains
=>
[
1
]
},
override
=>
{
percentage_complete
=>
{
contains
=>
[
1
,
2
,
3
]
},
}
},
],
notsubstring
=>
[
{
contains
=>
[
2
,
3
,
4
,
5
],
value
=>
'<1>'
},
{
contains
=>
[
2
,
3
,
4
,
5
],
value
=>
'<1>'
,
override
=>
{
percentage_complete
=>
{
contains
=>
[
4
,
5
]
},
},
}
],
regexp
=>
[
{
contains
=>
[
1
],
value
=>
'<1>'
,
escape
=>
1
},
{
contains
=>
[
1
],
value
=>
'<1>'
,
escape
=>
1
,
override
=>
{
percentage_complete
=>
{
value
=>
'^10'
},
}
},
{
contains
=>
[
1
],
value
=>
'^1-'
,
override
=>
REGEX_OVERRIDE
},
],
notregexp
=>
[
{
contains
=>
[
2
,
3
,
4
,
5
],
value
=>
'<1>'
,
escape
=>
1
},
{
contains
=>
[
2
,
3
,
4
,
5
],
value
=>
'<1>'
,
escape
=>
1
,
override
=>
{
percentage_complete
=>
{
value
=>
'^10'
},
}
},
{
contains
=>
[
2
,
3
,
4
,
5
],
value
=>
'^1-'
,
override
=>
REGEX_OVERRIDE
},
],
lessthan
=>
[
...
...
@@ -1031,14 +1026,26 @@ use constant TESTS => {
],
anywordssubstr
=>
[
{
contains
=>
[
1
,
2
],
value
=>
'<1> <2>'
,
override
=>
{
ANY_OVERRIDE
}
},
override
=>
{
ANY_OVERRIDE
,
percentage_complete
=>
{
contains
=>
[
1
,
2
,
3
]
},
}
},
],
allwordssubstr
=>
[
{
contains
=>
[
1
],
value
=>
'<1>'
,
override
=>
{
MULTI_BOOLEAN_OVERRIDE
}
},
override
=>
{
MULTI_BOOLEAN_OVERRIDE
,
# We search just the number "1" for percentage_complete,
# which matches a lot of bugs.
percentage_complete
=>
{
contains
=>
[
1
,
2
,
3
]
},
},
},
{
contains
=>
[]
,
value
=>
'<1>,<2>'
,
override
=>
{
dependson
=>
{
value
=>
'<1-id> <3-id>'
,
contains
=>
[]
},
# bug 3 has the value "21" here, so matches "2,1"
percentage_complete
=>
{
value
=>
'<2>,<3>'
,
contains
=>
[
3
]
}
}
},
],
...
...
@@ -1048,6 +1055,7 @@ use constant TESTS => {
# longdescs.isprivate translates to "1 0", so no bugs should
# show up.
'longdescs.isprivate'
=>
{
contains
=>
[]
},
percentage_complete
=>
{
contains
=>
[
4
,
5
]
},
# 1.0 0.0 exludes bug 5.
# XXX However, it also shouldn't match 2, 3, or 4, because
# they contain at least one comment with 0.0 work_time.
...
...
xt/lib/Bugzilla/Test/Search/FieldTest.pm
View file @
daa533e7
...
...
@@ -166,7 +166,9 @@ sub transformed_value_was_equal {
sub
bug_is_contained
{
my
(
$self
,
$number
)
=
@_
;
my
$contains
=
$self
->
test
->
{
contains
};
if
(
$self
->
transformed_value_was_equal
(
$number
))
{
if
(
$self
->
transformed_value_was_equal
(
$number
)
and
!
$self
->
test
->
{
override
}
->
{
$self
->
field
}
->
{
contains
})
{
$contains
=
$self
->
test
->
{
if_equal
}
->
{
contains
};
}
return
grep
(
$_
==
$number
,
@$contains
)
?
1
:
0
;
...
...
@@ -482,11 +484,6 @@ sub _substr_value {
$substr_size
+=
length
(
$field
);
}
my
$string
=
substr
(
$value
,
0
,
$substr_size
);
# Make percentage_complete substrings strings match integers uniquely,
# by searching for the full decimal number.
if
(
$field
eq
'percentage_complete'
and
length
(
$string
)
<
$substr_size
)
{
$string
.=
".000"
;
}
return
$string
;
}
return
substr
(
$value
,
$substr_size
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment