Skip to main content

contextdb_cli/
formatter.rs

1use contextdb_core::Value;
2use contextdb_engine::QueryResult;
3
4pub fn format_query_result(result: &QueryResult) -> String {
5    format_query_result_with_empty_headers(result, false)
6}
7
8pub fn format_query_result_with_empty_headers(
9    result: &QueryResult,
10    show_empty_headers: bool,
11) -> String {
12    if result.columns.is_empty() || (result.rows.is_empty() && !show_empty_headers) {
13        return String::new();
14    }
15
16    let mut widths: Vec<usize> = result.columns.iter().map(|c| c.len()).collect();
17
18    let rows: Vec<Vec<String>> = result
19        .rows
20        .iter()
21        .map(|row| row.iter().map(value_to_string).collect())
22        .collect();
23
24    for row in &rows {
25        for (i, cell) in row.iter().enumerate() {
26            if i < widths.len() {
27                widths[i] = widths[i].max(cell.len());
28            }
29        }
30    }
31
32    let sep = widths
33        .iter()
34        .map(|w| format!("+{}", "-".repeat(*w + 2)))
35        .collect::<String>()
36        + "+";
37
38    let mut out = String::new();
39    out.push_str(&sep);
40    out.push('\n');
41
42    out.push('|');
43    for (i, col) in result.columns.iter().enumerate() {
44        out.push(' ');
45        out.push_str(&format!("{:<width$}", col, width = widths[i]));
46        out.push(' ');
47        out.push('|');
48    }
49    out.push('\n');
50
51    out.push_str(&sep);
52    out.push('\n');
53
54    for row in rows {
55        out.push('|');
56        for (i, cell) in row.iter().enumerate() {
57            out.push(' ');
58            out.push_str(&format!("{:<width$}", cell, width = widths[i]));
59            out.push(' ');
60            out.push('|');
61        }
62        out.push('\n');
63    }
64
65    out.push_str(&sep);
66    out
67}
68
69fn value_to_string(v: &Value) -> String {
70    match v {
71        Value::Null => "NULL".to_string(),
72        Value::Bool(b) => b.to_string(),
73        Value::Int64(i) => i.to_string(),
74        Value::Float64(f) => f.to_string(),
75        Value::Text(s) => s.clone(),
76        Value::Uuid(u) => u.to_string(),
77        Value::Timestamp(ts) => ts.to_string(),
78        Value::Json(j) => j.to_string(),
79        Value::Vector(vec) => format!("{:?}", vec),
80        Value::TxId(tx) => tx.0.to_string(),
81    }
82}