~launchpad-pqm/launchpad/devel

« back to all changes in this revision

Viewing changes to lib/lp/bugs/model/bug.py

  • Committer: Launchpad Patch Queue Manager
  • Date: 2011-06-08 00:14:25 UTC
  • mfrom: (13165.2.2 bug-793809)
  • Revision ID: launchpad@pqm.canonical.com-20110608001425-i7noud89pt3iy93y
[r=wgrant][bug=793809] Use BugSummary to do tag portlet calculations

Show diffs side-by-side

added added

removed removed

Lines of Context:
63
63
    Select,
64
64
    SQL,
65
65
    SQLRaw,
 
66
    Sum,
66
67
    Union,
67
68
    )
68
69
from storm.info import ClassAlias
242
243
    tag = StringCol(notNull=True)
243
244
 
244
245
 
245
 
# We need to always use the same Count instance or the
246
 
# get_bug_tags_open_count is not UNIONable.
247
 
tag_count_columns = (BugTag.tag, Count())
248
 
 
249
 
 
250
246
def get_bug_tags(context_clause):
251
247
    """Return all the bug tags as a list of strings.
252
248
 
266
262
    return shortlist([row[0] for row in cur.fetchall()])
267
263
 
268
264
 
269
 
def get_bug_tags_open_count(context_condition, user, wanted_tags=None):
270
 
    """Return all the used bug tags with their open bug count.
271
 
 
 
265
def get_bug_tags_open_count(context_condition, user, tag_limit=0,
 
266
    include_tags=None):
 
267
    """Worker for IBugTarget.getUsedBugTagsWithOpenCounts.
 
268
 
 
269
    See `IBugTarget` for details.
 
270
 
 
271
    The only change is that this function takes a SQL expression for limiting
 
272
    the found tags.
272
273
    :param context_condition: A Storm SQL expression, limiting the
273
274
        used tags to a specific context. Only the BugTask table may be
274
275
        used to choose the context.
275
 
    :param user: The user performing the search.
276
 
    :param wanted_tags: A set of tags within which to restrict the search.
277
 
 
278
 
    :return: A list of tuples, (tag name, open bug count).
279
276
    """
280
 
    tables = (
281
 
        BugTag,
282
 
        Join(BugTask, BugTask.bugID == BugTag.bugID),
283
 
        )
 
277
    # Circular fail.
 
278
    from lp.bugs.model.bugsummary import BugSummary
 
279
    tags = {}
 
280
    if include_tags:
 
281
        tags = dict((tag, 0) for tag in include_tags)
 
282
    store = getUtility(IStoreSelector).get(MAIN_STORE, DEFAULT_FLAVOR)
 
283
    admin_team = getUtility(ILaunchpadCelebrities).admin
 
284
    if user is not None and not user.inTeam(admin_team):
 
285
        store = store.with_(SQL(
 
286
            "teams AS ("
 
287
            "SELECT team from TeamParticipation WHERE person=?)", (user.id,)))
284
288
    where_conditions = [
285
 
        BugTask.status.is_in(UNRESOLVED_BUGTASK_STATUSES),
 
289
        BugSummary.status.is_in(UNRESOLVED_BUGTASK_STATUSES),
 
290
        BugSummary.tag != None,
286
291
        context_condition,
287
292
        ]
288
 
    if wanted_tags is not None:
289
 
        where_conditions.append(BugTag.tag.is_in(wanted_tags))
290
 
    privacy_filter = get_bug_privacy_filter(user)
291
 
    if privacy_filter:
292
 
        # The EXISTS sub-select avoids a join against Bug, improving
293
 
        # performance significantly.
 
293
    if user is None:
 
294
        where_conditions.append(BugSummary.viewed_by_id == None)
 
295
    elif not user.inTeam(admin_team):
294
296
        where_conditions.append(
295
 
            Exists(Select(
296
 
                columns=[True], tables=[Bug],
297
 
                where=And(Bug.id == BugTag.bugID, SQLRaw(privacy_filter)))))
298
 
    store = getUtility(IStoreSelector).get(MAIN_STORE, DEFAULT_FLAVOR)
299
 
    return store.using(*tables).find(
300
 
        tag_count_columns, *where_conditions).group_by(BugTag.tag).order_by(
301
 
            Desc(Count()), BugTag.tag)
 
297
            Or(
 
298
                BugSummary.viewed_by_id == None,
 
299
                BugSummary.viewed_by_id.is_in(SQL("SELECT team FROM teams"))
 
300
                ))
 
301
    tag_count_columns = (BugSummary.tag, Sum(BugSummary.count))
 
302
    # Always query for used
 
303
    def _query(*args):
 
304
        return store.find(tag_count_columns, *(where_conditions + list(args))
 
305
            ).group_by(BugSummary.tag).order_by(
 
306
            Desc(Sum(BugSummary.count)), BugSummary.tag)
 
307
    used = _query()
 
308
    if tag_limit:
 
309
        used = used[:tag_limit]
 
310
    if include_tags:
 
311
        # Union in a query for just include_tags.
 
312
        used = used.union(_query(BugSummary.tag.is_in(include_tags)))
 
313
    tags.update(dict(used))
 
314
    return tags
302
315
 
303
316
 
304
317
class BugBecameQuestionEvent: