use anyhow::anyhow;
use nu_protocol::Config;
use nu_table::Table;
use nu_table::{Alignments, StyledString, TableTheme, TextStyle};
use odbc_api::buffers::TextRowSet;
use odbc_api::Cursor;
use std::collections::HashMap;
pub trait Print: Sized {
fn print_all_tables(self) -> anyhow::Result<()> {
let p = self.table_string()?;
debug!("\n{}", p);
Ok(())
}
fn convert_table(self) -> anyhow::Result<Table>;
fn table_string(self) -> anyhow::Result<String> {
let table = self.convert_table()?;
let cfg = Config::default();
let styles = HashMap::default();
let alignments = Alignments::default();
let p = table
.draw_table(&cfg, &styles, alignments, usize::MAX)
.ok_or_else(|| anyhow!("convert table to string error"))?;
Ok(p)
}
}
const BATCH_SIZE: usize = 128;
impl<T> Print for T
where
T: Cursor,
{
fn convert_table(mut self) -> anyhow::Result<Table> {
let headers: Vec<StyledString> = self
.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 self, Some(4096))?;
let mut row_set_cursor = self.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)
}
}