@@ -35,16 +35,56 @@ def is_explainable(sql):
3535 return sql .strip ().upper ().startswith (EXPLAINABLE_PREFIXES )
3636
3737
38+ _pg_cost_re = re .compile (r'\(cost=[\d.]+\.\.([\d.]+)' )
39+
40+
41+ def _cell_cost (cell ):
42+ """Extract the total cost from a PostgreSQL EXPLAIN cell, or numeric value from a plain numeric cell."""
43+ cell_str = str (cell )
44+ m = _pg_cost_re .search (cell_str )
45+ if m :
46+ return float (m .group (1 ))
47+ if isinstance (cell , (int , float )):
48+ return abs (float (cell ))
49+ if isinstance (cell , str ):
50+ try :
51+ return abs (float (cell ))
52+ except (ValueError , TypeError ):
53+ pass
54+ return None
55+
56+
3857def format_explain_output (headers , rows ):
58+ # Find max cost per column to scale bars
59+ num_cols = len (headers ) if headers else (len (rows [0 ]) if rows else 0 )
60+ col_max = [0.0 ] * num_cols
61+
62+ for row in rows :
63+ for j , cell in enumerate (row ):
64+ cost = _cell_cost (cell )
65+ if cost is not None :
66+ col_max [j ] = max (col_max [j ], cost )
67+
68+ base_style = 'border: 1px solid #666; padding: 4px 8px; white-space: pre'
69+
3970 parts = ['<table style="border-collapse: collapse; margin: 8px 0; font-size: 13px">' ]
4071 parts .append ('<tr>' )
4172 for h in headers :
42- parts .append (f'<th style="border: 1px solid #666; padding: 4px 8px ; text-align: left">{ h } </th>' )
73+ parts .append (f'<th style="{ base_style } ; text-align: left">{ h } </th>' )
4374 parts .append ('</tr>' )
4475 for row in rows :
4576 parts .append ('<tr>' )
46- for cell in row :
47- parts .append (f'<td style="border: 1px solid #666; padding: 4px 8px">{ cell } </td>' )
77+ for j , cell in enumerate (row ):
78+ cost = _cell_cost (cell ) if j < num_cols else None
79+ if cost is not None and col_max [j ] > 0 :
80+ pct = cost / col_max [j ] * 100
81+ parts .append (
82+ f'<td style="{ base_style } ;'
83+ f' background: linear-gradient(to right, rgba(79,79,255,0.3) { pct :.1f} %, transparent { pct :.1f} %)"'
84+ f'>{ cell } </td>'
85+ )
86+ else :
87+ parts .append (f'<td style="{ base_style } ">{ cell } </td>' )
4888 parts .append ('</tr>' )
4989 parts .append ('</table>' )
5090 return '' .join (parts )
0 commit comments