1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
|
# Copyright 2009-2011 Canonical Ltd. This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).
"""Find OOPS References within the LP database."""
__metaclass__ = type
__all__ = [
'referenced_oops',
]
import re
from lp.services.database.sqlbase import (
cursor,
sqlvalues,
)
def referenced_oops(start_date, end_date, context_clause, context_params):
'''Find OOPS codes that are referenced somewhere in Launchpad.
This returns OOPS references from:
- any message, message chunk or bug.
- any question that passes context_clause.
Privacy and access controls are ignored: the maximum disclosure is a
single word immediately after the word 'OOPS'. Future iterations may
tighten up the returned references.
:param start_date: The earliest modification date to consider.
:param end_date: The last modification date to consider.
:param context_clause: A filter to restrict the question clause against.
For instance: 'product=%(product)s'.
:param context_params: Parameters needed to evaluate context_clause.
For instance: {'product': 12}
:return: A set of the found OOPS ids.
'''
# Note that the POSIX regexp syntax is subtly different to the Python,
# and that we need to escape all \ characters to keep the SQL interpreter
# happy.
posix_oops_match = (r"~* '^(oops-\\w+)|(\\moops-\\w+)'")
params = dict(start_date=start_date, end_date=end_date)
params.update(context_params)
sql_params = sqlvalues(**params)
sql_params['posix_oops_match'] = posix_oops_match
query = ("""
WITH recent_messages AS
(SELECT id FROM Message WHERE
datecreated BETWEEN %(start_date)s AND %(end_date)s)
SELECT DISTINCT subject FROM Message
WHERE subject %(posix_oops_match)s AND subject IS NOT NULL
AND id IN (SELECT id FROM recent_messages)
UNION ALL
SELECT content FROM MessageChunk WHERE content %(posix_oops_match)s
AND message IN (SELECT id FROM recent_messages)
UNION ALL
SELECT title || ' ' || description
FROM Bug WHERE
date_last_updated BETWEEN %(start_date)s AND %(end_date)s AND
(title %(posix_oops_match)s OR description %(posix_oops_match)s)
UNION ALL
SELECT title || ' ' || description || ' ' || COALESCE(whiteboard,'')
FROM Question WHERE """ + context_clause + """
AND (datelastquery BETWEEN %(start_date)s AND %(end_date)s
OR datelastresponse BETWEEN %(start_date)s AND %(end_date)s)
AND (title %(posix_oops_match)s
OR description %(posix_oops_match)s
OR whiteboard %(posix_oops_match)s)
""") % sql_params
referenced_codes = set()
oops_re = re.compile(r'(?i)(?P<oops>\boops-\w+)')
cur = cursor()
cur.execute(query)
for content in (row[0] for row in cur.fetchall()):
for oops in oops_re.findall(content):
referenced_codes.add(oops.upper())
return referenced_codes
|