launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #02378
[Merge] lp:~lifeless/launchpad/bug-705224 into lp:launchpad
Robert Collins has proposed merging lp:~lifeless/launchpad/bug-705224 into lp:launchpad.
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
Related bugs:
#705224 Distribution:EntryResource:searchTasks timeout
https://bugs.launchpad.net/bugs/705224
For more details, see:
https://code.launchpad.net/~lifeless/launchpad/bug-705224/+merge/46873
Our bug search is UNIONing tag lookups together, but this performs poorly - the planner does separate traversals in the inner loop rather than combining the constraints; this changes the UNION into a simpler IN.
--
https://code.launchpad.net/~lifeless/launchpad/bug-705224/+merge/46873
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~lifeless/launchpad/bug-705224 into lp:launchpad.
=== modified file 'lib/lp/bugs/model/bugtask.py'
--- lib/lp/bugs/model/bugtask.py 2011-01-14 21:20:46 +0000
+++ lib/lp/bugs/model/bugtask.py 2011-01-20 04:56:15 +0000
@@ -1401,6 +1401,7 @@
:param tags: An iterable of valid tag names (not prefixed minus
signs, not wildcards).
"""
+ tags = list(tags)
if tags == []:
return None
@@ -1411,6 +1412,20 @@
for tag in sorted(tags))
+def _build_tag_set_query_any(tags):
+ """Return a query fragment for bugs matching any tag.
+
+ :param tags: An iterable of valid tags without - or + and not wildcards.
+ :return: A string SQL query fragment or None if no tags were provided.
+ """
+ tags = list(tags)
+ if tags == []:
+ return None
+ return ("EXISTS (SELECT TRUE FROM BugTag WHERE "
+ "BugTag.bug = Bug.id AND BugTag.tag IN %s)"
+ % sqlvalues(sorted(tags)))
+
+
def build_tag_search_clause(tags_spec):
"""Return a tag search clause.
@@ -1438,14 +1453,14 @@
include_clause = build_tag_set_query("INTERSECT", include)
# The set of bugs that have *any* of the tags requested for
# *exclusion*.
- exclude_clause = build_tag_set_query("UNION", exclude)
+ exclude_clause = _build_tag_set_query_any(exclude)
else:
# How to combine an include clause and an exclude clause when
# both are generated.
combine_with = 'OR'
# The set of bugs that have *any* of the tags requested for
# inclusion.
- include_clause = build_tag_set_query("UNION", include)
+ include_clause = _build_tag_set_query_any(include)
# The set of bugs that have *all* of the tags requested for
# exclusion.
exclude_clause = build_tag_set_query("INTERSECT", exclude)
=== modified file 'lib/lp/bugs/model/tests/test_bugtask.py'
--- lib/lp/bugs/model/tests/test_bugtask.py 2011-01-14 12:05:24 +0000
+++ lib/lp/bugs/model/tests/test_bugtask.py 2011-01-20 04:56:15 +0000
@@ -211,26 +211,33 @@
self.assertEqual(self.searchClause(any()), None)
self.assertEqual(self.searchClause(all()), None)
- def test_single_tag_presence(self):
+ def test_single_tag_presence_any(self):
# The WHERE clause to test for the presence of a single
- # tag. Should be the same for an `any` query or an `all`
- # query.
+ # tag where at least one tag is desired.
expected_query = (
"""EXISTS
(SELECT TRUE FROM BugTag
WHERE BugTag.bug = Bug.id
- AND BugTag.tag = 'fred')""")
+ AND BugTag.tag IN ('fred'))""")
self.assertEqualIgnoringWhitespace(
expected_query,
self.searchClause(any(u'fred')))
+
+ def test_single_tag_presence_all(self):
+ # The WHERE clause to test for the presence of a single
+ # tag where all tags are desired.
+ expected_query = (
+ """EXISTS
+ (SELECT TRUE FROM BugTag
+ WHERE BugTag.bug = Bug.id
+ AND BugTag.tag = 'fred')""")
self.assertEqualIgnoringWhitespace(
expected_query,
self.searchClause(all(u'fred')))
- def test_single_tag_absence(self):
+ def test_single_tag_absence_any(self):
# The WHERE clause to test for the absence of a single
- # tag. Should be the same for an `any` query or an `all`
- # query.
+ # tag where at least one tag is desired.
expected_query = (
"""NOT EXISTS
(SELECT TRUE FROM BugTag
@@ -239,6 +246,15 @@
self.assertEqualIgnoringWhitespace(
expected_query,
self.searchClause(any(u'-fred')))
+
+ def test_single_tag_absence_all(self):
+ # The WHERE clause to test for the absence of a single
+ # tag where all tags are desired.
+ expected_query = (
+ """NOT EXISTS
+ (SELECT TRUE FROM BugTag
+ WHERE BugTag.bug = Bug.id
+ AND BugTag.tag IN ('fred'))""")
self.assertEqualIgnoringWhitespace(
expected_query,
self.searchClause(all(u'-fred')))
@@ -278,11 +294,7 @@
"""EXISTS
(SELECT TRUE FROM BugTag
WHERE BugTag.bug = Bug.id
- AND BugTag.tag = 'bob'
- UNION
- SELECT TRUE FROM BugTag
- WHERE BugTag.bug = Bug.id
- AND BugTag.tag = 'fred')""",
+ AND BugTag.tag IN ('bob', 'fred'))""",
self.searchClause(any(u'fred', u'bob')))
# In an `any` query, a positive wildcard is dominant over
# other positive tags because "bugs with one or more tags" is
@@ -347,11 +359,7 @@
"""NOT EXISTS
(SELECT TRUE FROM BugTag
WHERE BugTag.bug = Bug.id
- AND BugTag.tag = 'bob'
- UNION
- SELECT TRUE FROM BugTag
- WHERE BugTag.bug = Bug.id
- AND BugTag.tag = 'fred')""",
+ AND BugTag.tag IN ('bob', 'fred'))""",
self.searchClause(all(u'-fred', u'-bob')))
# In an `all` query, a negative wildcard is dominant over
# other negative tags because "bugs without any tags" is a
@@ -371,7 +379,7 @@
"""(EXISTS
(SELECT TRUE FROM BugTag
WHERE BugTag.bug = Bug.id
- AND BugTag.tag = 'fred')
+ AND BugTag.tag IN ('fred'))
OR NOT EXISTS
(SELECT TRUE FROM BugTag
WHERE BugTag.bug = Bug.id
@@ -381,11 +389,7 @@
"""(EXISTS
(SELECT TRUE FROM BugTag
WHERE BugTag.bug = Bug.id
- AND BugTag.tag = 'eric'
- UNION
- SELECT TRUE FROM BugTag
- WHERE BugTag.bug = Bug.id
- AND BugTag.tag = 'fred')
+ AND BugTag.tag IN ('eric', 'fred'))
OR NOT EXISTS
(SELECT TRUE FROM BugTag
WHERE BugTag.bug = Bug.id
@@ -415,11 +419,7 @@
"""(EXISTS
(SELECT TRUE FROM BugTag
WHERE BugTag.bug = Bug.id
- AND BugTag.tag = 'eric'
- UNION
- SELECT TRUE FROM BugTag
- WHERE BugTag.bug = Bug.id
- AND BugTag.tag = 'fred')
+ AND BugTag.tag IN ('eric', 'fred'))
OR NOT EXISTS
(SELECT TRUE FROM BugTag
WHERE BugTag.bug = Bug.id
@@ -431,11 +431,7 @@
"""(EXISTS
(SELECT TRUE FROM BugTag
WHERE BugTag.bug = Bug.id
- AND BugTag.tag = 'eric'
- UNION
- SELECT TRUE FROM BugTag
- WHERE BugTag.bug = Bug.id
- AND BugTag.tag = 'fred')
+ AND BugTag.tag IN ('eric', 'fred'))
OR NOT EXISTS
(SELECT TRUE FROM BugTag
WHERE BugTag.bug = Bug.id))""",
@@ -465,7 +461,7 @@
AND NOT EXISTS
(SELECT TRUE FROM BugTag
WHERE BugTag.bug = Bug.id
- AND BugTag.tag = 'bob'))""",
+ AND BugTag.tag IN ('bob')))""",
self.searchClause(all(u'fred', u'-bob')))
self.assertEqualIgnoringWhitespace(
"""(EXISTS
@@ -479,11 +475,7 @@
AND NOT EXISTS
(SELECT TRUE FROM BugTag
WHERE BugTag.bug = Bug.id
- AND BugTag.tag = 'bob'
- UNION
- SELECT TRUE FROM BugTag
- WHERE BugTag.bug = Bug.id
- AND BugTag.tag = 'harry'))""",
+ AND BugTag.tag IN ('bob', 'harry')))""",
self.searchClause(all(u'fred', u'-bob', u'eric', u'-harry')))
# The positive wildcard is superfluous in the presence of
# other positive tags.
@@ -495,11 +487,7 @@
AND NOT EXISTS
(SELECT TRUE FROM BugTag
WHERE BugTag.bug = Bug.id
- AND BugTag.tag = 'bob'
- UNION
- SELECT TRUE FROM BugTag
- WHERE BugTag.bug = Bug.id
- AND BugTag.tag = 'harry'))""",
+ AND BugTag.tag IN ('bob', 'harry')))""",
self.searchClause(all(u'fred', u'-bob', u'*', u'-harry')))
# The positive wildcard is not superfluous in the absence of
# other positive tags.
@@ -510,11 +498,7 @@
AND NOT EXISTS
(SELECT TRUE FROM BugTag
WHERE BugTag.bug = Bug.id
- AND BugTag.tag = 'bob'
- UNION
- SELECT TRUE FROM BugTag
- WHERE BugTag.bug = Bug.id
- AND BugTag.tag = 'harry'))""",
+ AND BugTag.tag IN ('bob', 'harry')))""",
self.searchClause(all(u'-bob', u'*', u'-harry')))
# The negative wildcard is dominant over other negative tags.
self.assertEqualIgnoringWhitespace(