mbligh | 2e4e5df | 2007-11-05 17:22:46 +0000 | [diff] [blame^] | 1 | #!/usr/bin/python |
| 2 | |
| 3 | """ |
| 4 | Selects all rows and columns that satisfy the condition specified |
| 5 | and draws the matrix. There is a seperate SQL query made for every (x,y) |
| 6 | in the matrix. |
| 7 | """ |
| 8 | |
| 9 | |
| 10 | print "Content-type: text/html\n" |
| 11 | import cgi, cgitb, re |
| 12 | import sys |
| 13 | |
| 14 | tko = os.path.dirname(os.path.realpath(os.path.abspath(sys.argv[0]))) |
| 15 | sys.path.insert(0, tko) |
| 16 | |
| 17 | import display, frontend, db |
| 18 | |
| 19 | cgitb.enable() |
| 20 | db = db.db() |
| 21 | |
| 22 | def 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 | |
| 39 | def 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 | |
| 53 | def 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 | |
| 82 | def 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 | |
| 141 | main() |