odbc_common/
print_table.rs1use anyhow::anyhow;
2use nu_protocol::Config;
3use nu_table::Table;
4use nu_table::{Alignments, StyledString, TableTheme, TextStyle};
5use odbc_api::buffers::TextRowSet;
6use odbc_api::Cursor;
7use std::collections::HashMap;
8
9pub trait Print: Sized {
10 fn print_all_tables(self) -> anyhow::Result<()> {
11 let p = self.table_string()?;
12 debug!("\n{}", p);
13 Ok(())
14 }
15
16 fn convert_table(self) -> anyhow::Result<Table>;
17
18 fn table_string(self) -> anyhow::Result<String> {
19 let table = self.convert_table()?;
20 let cfg = Config::default();
21 let styles = HashMap::default();
22 let alignments = Alignments::default();
23
24 let p = table
25 .draw_table(&cfg, &styles, alignments, usize::MAX)
26 .ok_or_else(|| anyhow!("convert table to string error"))?;
27 Ok(p)
28 }
29}
30
31const BATCH_SIZE: usize = 128;
32
33impl<T> Print for T
44where
45 T: Cursor,
46{
47 fn convert_table(mut self) -> anyhow::Result<Table> {
48 let headers: Vec<StyledString> = self
49 .column_names()?
50 .collect::<Result<Vec<String>, _>>()?
51 .into_iter()
52 .map(|x| StyledString::new(x, TextStyle::default_header()))
53 .collect();
54
55 let mut buffers = TextRowSet::for_cursor(BATCH_SIZE, &mut self, Some(4096))?;
58 let mut row_set_cursor = self.bind_buffer(&mut buffers)?;
60 let mut rows = vec![];
61 while let Some(batch) = row_set_cursor.fetch()? {
63 for row_index in 0..batch.num_rows() {
65 let row_data = (0..batch.num_cols())
67 .map(|col_index| batch.at(col_index, row_index).unwrap_or(&[]))
68 .into_iter()
69 .map(|x| String::from_utf8_lossy(x).to_string())
70 .map(|x| StyledString::new(x, TextStyle::basic_left()))
71 .collect();
72 rows.push(row_data);
73 }
74 }
75 let table = Table::new(headers, rows, TableTheme::rounded());
76
77 Ok(table)
78 }
79}