1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
use nu_protocol::Config;
use nu_table::{Alignments, StyledString, Table, TableTheme, TextStyle};
use odbc_api::buffers::TextRowSet;
use odbc_api::Cursor;
use std::collections::HashMap;
use std::error::Error;
const BATCH_SIZE: usize = 5000;
pub fn print_all_tables(cursor: impl Cursor) -> Result<(), Box<dyn Error>> {
let table = convert_table(cursor)?;
let string = convert_table_string(table).ok_or("convert table to string error")?;
debug!("\n{}", string);
Ok(())
}
pub fn convert_table(mut cursor: impl Cursor) -> Result<Table, Box<dyn Error>> {
let headers: Vec<StyledString> = cursor
.column_names()?
.collect::<Result<Vec<String>, _>>()?
.into_iter()
.map(|x| StyledString::new(x, TextStyle::default_header()))
.collect();
let mut buffers = TextRowSet::for_cursor(BATCH_SIZE, &mut cursor, Some(4096))?;
let mut row_set_cursor = cursor.bind_buffer(&mut buffers)?;
let mut rows = vec![];
while let Some(batch) = row_set_cursor.fetch()? {
for row_index in 0..batch.num_rows() {
let row_data = (0..batch.num_cols())
.map(|col_index| batch.at(col_index, row_index).unwrap_or(&[]))
.into_iter()
.map(|x| String::from_utf8_lossy(x).to_string())
.map(|x| StyledString::new(x, TextStyle::basic_left()))
.collect();
rows.push(row_data);
}
}
let table = Table::new(headers, rows, TableTheme::rounded());
Ok(table)
}
pub fn convert_table_string(table: Table) -> Option<String> {
let cfg = Config::default();
let styles = HashMap::default();
let alignments = Alignments::default();
table.draw_table(&cfg, &styles, alignments, usize::MAX)
}