Skip to main content

lean_ctx_patterns/
mysql.rs

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