blob: e20a66710aa2935b842967b32438a4e66ec49663 [file] [log] [blame]
mbligh2b672532007-11-05 19:24:51 +00001#!/usr/bin/python
2"""
3This library provides a bunch of miscellaneous parameter parsing,
4sql generating and list cleanup library functions that are used
5by both the reporting cli and web interface.
6"""
7
8import sys, os, re
9
10tko = os.path.dirname(os.path.realpath(os.path.abspath(sys.argv[0])))
11sys.path.insert(0, tko)
12
13import display, frontend, db
14
15db = db.db()
16
mbligh12eebfa2008-01-03 02:01:53 +000017def dprint(str):
18 pass
19 #print "! %s<br>" % str
20
21def parse_scrub_and_gen_condition(condition, valid_field_dict):
22 me = parse_scrub_and_gen_condition # shorten the name
23 compare_ops = {'=':'=', '<>':'<>', '==':'=', '!=':'<>', '>':'>',
24 '<':'<', '>=':'>=', '<=':'<=', '~':'LIKE', '#':'REGEXP'}
25
26 # strip white space
27 condition = condition.strip()
28
29 # ()'s
30 #match = re.match(r'^[(](.+)[)]$', condition)
31 #if match:
32 # dprint("Matched () on %s" % condition)
33 # depth = 0
34 # for c in match.group(1):
35 # if c == '(': depth += 1
36 # if c == ')': depth -= 1
37 # if depth < 0: break
38 # dprint("Depth is %d" % depth)
39 # if depth == 0:
40 # dprint("Match...stripping ()'s")
41 # return me(match.group(1), valid_field_dict)
42
43 # OR
44 match = re.match(r'^(.+)[|](.+)$', condition)
45 if match:
46 dprint("Matched | on %s" % condition)
47 (a_sql, a_values) = me(match.group(1), valid_field_dict)
48 (b_sql, b_values) = me(match.group(2), valid_field_dict)
49 return (" (%s) OR (%s) " % (a_sql, b_sql),
50 a_values + b_values)
51
52 # AND
53 match = re.match(r'^(.+)[&](.+)$', condition)
54 if match:
55 dprint("Matched & on %s" % condition)
56 (a_sql, a_values) = me(match.group(1), valid_field_dict)
57 (b_sql, b_values) = me(match.group(2), valid_field_dict)
58 return (" (%s) AND (%s) " % (a_sql, b_sql),
59 a_values + b_values)
60
61 # NOT
62 #match = re.match(r'^[!](.+)$', condition)
63 #if match:
64 # dprint("Matched ! on %s" % condition)
65 # (sql, values) = me(match.group(1), valid_field_dict)
66 # return (" NOT (%s) " % (sql,), values)
67
68 # '<field> <op> <value>' where value can be quoted
69 # double quotes are escaped....i.e. '''' is the same as "'"
70 regex = r'^(%s)[ \t]*(%s)[ \t]*' + \
71 r'(\'((\'\'|[^\'])*)\'|"((""|[^"])*)"|([^\'"].*))$'
72 regex = regex % ('|'.join(valid_field_dict.keys()),
73 '|'.join(compare_ops.keys()))
74 match = re.match(regex, condition)
75 if match:
76 field = valid_field_dict[match.group(1)]
77 op = compare_ops[match.group(2)]
78 if match.group(5):
79 val = match.group(4).replace("''", "'")
80 elif match.group(7):
81 val = match.group(6).replace('""', '"')
82 elif match.group(8):
83 val = match.group(8)
84 else:
85 raise "Internal error"
86 return ("%s %s %%s" % (field, op), [val])
87
88
89 raise "Could not parse '%s' (%s)" % (condition, regex)
90
91
92###
93### Everything past here is depricated.
94###
95
mbligh2b672532007-11-05 19:24:51 +000096def generate_sql_condition(condition_list):
97 """ generate the sql for the condition list."""
98 sql = ''
99 value = []
100 for field, operator, values in condition_list:
101 if len(values) == 1:
102 if sql != '':
103 sql += " and "
104 sql += " %s%s%%s" % (field, operator)
105 value.append(values[0][0])
106 elif len(values) > 1:
107 expression = [" %s %s %%s" % (field, operator) for val in values]
108 for val in values:
109 value.append(val[0])
110 if sql != '':
111 sql += " and "
112 sql += "(%s)" % " or ".join(expression)
113 return sql, value
114
115
116def prune_list(thelist, condition_sql, condition_value):
117 """ keep track of which columns do not have any elements."""
118 pruned_list = []
119 for g in thelist:
120 # check for multiple index values in the db.
121 sql = "t where "
122 expr = [" %s = %%s" % (g.idx_name) for val in g.idx_value]
123 sql += " (%s) " % " or ".join(expr)
124 value = []
125 value.extend(g.idx_value)
126 if condition_sql:
127 sql += " and "
128 sql += condition_sql
129 value.extend(condition_value)
130 tests = frontend.test.select_sql(db, sql, value)
131 if len(tests) > 0:
132 pruned_list.append(g)
133 return pruned_list
134
135
136def parse_condition(condition):
137 """ parse the condition into independent clauses."""
138 condition_list = []
139 if not condition:
140 return condition_list
141 attribute_re = r"(\w+)"
142 op_re = r"(=|!=)"
143 value_re = r"('[^']*')"
144 # condition is clause & clause & ..
145 clause_re = r"%s\s*%s\s*%s" % (attribute_re, op_re, value_re)
146 condition_re = re.compile(r"^\s*%s(\s*&\s*%s)*\s*$" % (clause_re, clause_re))
147 if not condition_re.match(condition):
148 print "Condition not in the correct format: %s" % condition
149 sys.exit(0)
150 triples = []
151 for clause in [c.strip() for c in condition.split('&')]:
152 attribute, op, value = re.match(clause_re, clause).groups()
153 triples.append((attribute, op, value))
154 for (field_name, operator, value) in triples:
155 match, field = frontend.select(db, field_name, value, distinct=True)
156 if len(match) > 0:
157 condition_list.append((field, operator, match))
158 else:
159 print "No matching results found for condition %s." % \
160 condition
161 sys.exit(0)
162 return condition_list
163
164
165def get_value(test, field):
166 """ get specific field values from the given test object."""
167 if field == 'test':
168 return test.testname
169 elif field == 'kernel_idx':
170 return test.kernel_idx
171 elif field == 'machine_idx':
172 return test.machine_idx
173 elif field == 'status':
174 return test.status_num
175
176
177def get_tests(condition_sql, condition_value):
178 # get all the tests that satify the given condition.
179 if condition_sql:
180 sql = "t where "
181 sql += condition_sql
182 value = [str(val) for val in condition_value]
183 #print sql , value
184 tests = frontend.test.select_sql(db, sql, value)
185 else:
186 sql = None
187 value = None
188 tests = frontend.test.select_sql(db, " t ", None)
189 return tests