blob: 2eba013dbcadace5d8754b75067602cd69dd687f [file] [log] [blame]
mbligh2e4e5df2007-11-05 17:22:46 +00001#!/usr/bin/python
2
3"""
4Selects all rows and columns that satisfy the condition specified
5and draws the matrix. There is a seperate SQL query made for every (x,y)
6in the matrix.
7"""
8
9
10print "Content-type: text/html\n"
11import cgi, cgitb, re
12import sys
13
14tko = os.path.dirname(os.path.realpath(os.path.abspath(sys.argv[0])))
15sys.path.insert(0, tko)
16
17import display, frontend, db
18
19cgitb.enable()
20db = db.db()
21
22def generate_sql_condition(condition_list):
23 """ generate the sql for the condition list."""
24 sql = ""
25 value = []
26 for field, operator, values in condition_list:
27 if len(values) == 1:
28 sql += " and %s%s%%s" % (field, operator)
29 value.append(values[0][0])
30 elif len(values) > 1:
31 sql += " and "
32 expression = [" %s %s %%s" % (field, operator) for val in values]
33 for val in values:
34 value.append(val[0])
35 sql += "(%s)" % " or ".join(expression)
36 return sql, value
37
38
39def prune_list(thelist, condition_sql, condition_value):
40 """ keep track of which columns do not have any elements."""
41 pruned_list = []
42 for g in thelist:
43 sql = "t where %s=%%s " % g.idx_name
44 value = [g.idx_value]
45 sql += condition_sql
46 value.extend(condition_value)
47 tests = frontend.test.select_sql(db, sql, value)
48 if len(tests) > 0:
49 pruned_list.append(g)
50 return pruned_list
51
52
53def ParseCondition(condition):
54 """ parse the condition into independent clauses."""
55 condition_list = []
56 if not condition:
57 return condition_list
58 attribute_re = r"(\w+)"
59 op_re = r"(=|!=)"
60 value_re = r"('[^']*')"
61 # condition is clause & clause & ..
62 clause_re = r"%s\s*%s\s*%s" % (attribute_re, op_re, value_re)
63 condition_re = re.compile(r"^\s*%s(\s*&\s*%s)*\s*$" % (clause_re, clause_re))
64 if not condition_re.match(condition):
65 print "Condition not in the correct format: %s" % condition
66 sys.exit(0)
67 triples = []
68 for clause in [c.strip() for c in condition.split('&')]:
69 attribute, op, value = re.match(clause_re, clause).groups()
70 triples.append((attribute, op, value))
71 for (field_name, operator, value) in triples:
72 match, field = frontend.select(db, field_name, value)
73 if len(match) > 0:
74 condition_list.append((field, operator, match))
75 else:
76 print "No matching records found for condition %s." % \
77 condition
78 sys.exit(0)
79 return condition_list
80
81
82def main():
83
84 # parse the fields from the form.
85 form = cgi.FieldStorage()
86 columns = 'kernel'
87 rows = 'test'
88 condition = None
89 for field in form:
90 value = form[field].value
91 if field == 'columns':
92 columns = value
93 elif field == 'rows':
94 rows = value
95 elif field == 'condition':
96 condition = value
97
98 # parse the conditions into sql query and value list.
99 condition_sql = ""
100 condition_value = []
101 if condition:
102 condition_list = ParseCondition(condition)
103 condition_sql, condition_value = generate_sql_condition(condition_list)
104
105 # get all possible column values.
106 column_groups = frontend.anygroup.selectunique(db, columns)
107
108 # get all possible row values.
109 row_groups = frontend.anygroup.selectunique(db,rows)
110 # keep only those values in rows/columns that have a test
111 # corresponding to it.
112 row_groups = prune_list(row_groups, condition_sql, condition_value)
113 column_groups = prune_list(column_groups, condition_sql, condition_value)
114
115 # prepare the header for the table.
116 headers = [g.name for g in column_groups]
117
118 header_row = [display.box(x, header=True) for x in headers]
119 header_row.insert(0, display.box("", header=True))
120
121 matrix = [header_row]
122
123 for r_group in row_groups:
124 row = [display.box(r_group.name)]
125 # get individual unit values
126 for c_group in column_groups:
127 sql = "t where %s=%%s and %s=%%s" % (r_group.idx_name,
128 c_group.idx_name)
129 value = [r_group.idx_value, c_group.idx_value]
130 sql += condition_sql
131 value.extend(condition_value)
132 tests = frontend.test.select_sql(db, sql, value)
133 value_str = [str(val) for val in value]
134 link = 'test.cgi?sql=%s&values=%s' % \
135 (sql, ','.join(value_str))
136 row.append(display.status_count_box(db, tests, link))
137 matrix.append(row)
138 display.print_table(matrix)
139
140
141main()