Skip to main content

lean_ctx/core/patterns/
mysql.rs

1pub fn compress(cmd: &str, output: &str) -> Option<String> {
2    let trimmed = output.trim();
3    if trimmed.is_empty() {
4        return Some("ok".to_string());
5    }
6
7    if is_table_output(trimmed) {
8        return Some(compress_table(trimmed));
9    }
10
11    if cmd.contains("show databases") || cmd.contains("show tables") {
12        return Some(compress_show(trimmed));
13    }
14
15    if trimmed.starts_with("Query OK") || trimmed.starts_with("Empty set") {
16        return Some(trimmed.lines().next().unwrap_or(trimmed).to_string());
17    }
18
19    Some(compact_lines(trimmed, 20))
20}
21
22fn is_table_output(output: &str) -> bool {
23    let lines: Vec<&str> = output.lines().collect();
24    lines.len() >= 3
25        && lines
26            .iter()
27            .any(|l| l.starts_with('+') && l.contains("---"))
28}
29
30fn compress_table(output: &str) -> String {
31    let lines: Vec<&str> = output.lines().collect();
32    let data_lines: Vec<&&str> = lines
33        .iter()
34        .filter(|l| !l.starts_with('+') && !l.trim().is_empty())
35        .collect();
36
37    let row_count = if data_lines.len() > 1 {
38        data_lines.len() - 1
39    } else {
40        0
41    };
42
43    if row_count <= 20 {
44        return output.to_string();
45    }
46
47    let header_end = lines
48        .iter()
49        .enumerate()
50        .filter(|(_, l)| l.starts_with('+'))
51        .nth(1)
52        .map(|(i, _)| i + 1)
53        .unwrap_or(3);
54
55    let preview_end = (header_end + 10).min(lines.len());
56    let preview = &lines[..preview_end];
57    format!("{}\n... ({row_count} rows total)", preview.join("\n"))
58}
59
60fn compress_show(output: &str) -> String {
61    let items: Vec<&str> = output
62        .lines()
63        .filter(|l| !l.starts_with('+') && !l.trim().is_empty() && !l.contains("---"))
64        .filter(|l| !l.contains("Database") && !l.contains("Tables_in"))
65        .map(|l| l.trim().trim_matches('|').trim())
66        .filter(|l| !l.is_empty())
67        .collect();
68
69    if items.is_empty() {
70        return "empty".to_string();
71    }
72    if items.len() <= 30 {
73        return format!("{} items: {}", items.len(), items.join(", "));
74    }
75    format!(
76        "{} items: {}, ... +{} more",
77        items.len(),
78        items[..20].join(", "),
79        items.len() - 20
80    )
81}
82
83fn compact_lines(text: &str, max: usize) -> String {
84    let lines: Vec<&str> = text.lines().filter(|l| !l.trim().is_empty()).collect();
85    if lines.len() <= max {
86        return lines.join("\n");
87    }
88    format!(
89        "{}\n... ({} more lines)",
90        lines[..max].join("\n"),
91        lines.len() - max
92    )
93}