From bd1e965f936c9fe652bd940c1f12e3327f06a222 Mon Sep 17 00:00:00 2001 From: Jesse Luehrs Date: Sat, 10 Nov 2018 00:50:24 -0500 Subject: add sql subcommand for raw queries this was more painful than i think it should have been --- src/cmd/sql.rs | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 src/cmd/sql.rs (limited to 'src/cmd/sql.rs') diff --git a/src/cmd/sql.rs b/src/cmd/sql.rs new file mode 100644 index 0000000..ae398b5 --- /dev/null +++ b/src/cmd/sql.rs @@ -0,0 +1,77 @@ +use db; +use paths; + +pub fn run(query: &str, tsv: bool) -> failure::Fallible<()> { + let db = db::DB::new(&paths::db_path()?)?; + + let rows_cell = std::cell::Cell::new(Some(vec![])); + let cols = db.query(query, |row| { + let display_row: Vec = (0..row.column_count()) + .map(|i| row.get_raw(i)) + .map(|v| format_value(&v)) + .collect(); + let mut rows = rows_cell.replace(None).unwrap(); + rows.push(display_row); + rows_cell.replace(Some(rows)); + })?; + + let rows = rows_cell.into_inner().unwrap(); + + if tsv { + print_tsv(&rows); + } + else { + print_table(&cols, &rows); + } + + Ok(()) +} + +fn print_table(cols: &[String], rows: &[Vec]) { + let widths = column_widths(&cols, &rows); + + print_row(&widths, &cols); + let border: Vec = widths.iter().map(|l| "-".repeat(*l)).collect(); + println!("{}", &border.join("-+-")); + + for row in rows { + print_row(&widths, &row); + } +} + +fn print_tsv(rows: &[Vec]) { + for row in rows { + println!("{}", row.join("\t")); + } +} + +fn format_value(v: &rusqlite::types::ValueRef) -> String { + match v { + rusqlite::types::ValueRef::Null => "null".to_string(), + rusqlite::types::ValueRef::Integer(i) => format!("{}", i), + rusqlite::types::ValueRef::Real(f) => format!("{}", f), + rusqlite::types::ValueRef::Text(s) => format!("{}", s), + rusqlite::types::ValueRef::Blob(b) => format!("{:?}", b), + } +} + +fn column_widths(cols: &[String], rows: &[Vec]) -> Vec { + let mut max_widths: Vec = cols.iter().map(|s| s.len()).collect(); + for row in rows { + for (i, col) in row.iter().enumerate() { + if col.len() > max_widths[i] { + max_widths[i] = col.len(); + } + } + } + max_widths +} + +fn print_row(widths: &[usize], row: &[String]) { + let fixed_width_row: Vec = row + .iter() + .zip(widths.iter()) + .map(|(s, width)| format!("{:width$}", s, width=width)) + .collect(); + println!("{}", &fixed_width_row.join(" | ")); +} -- cgit v1.2.3-54-g00ecf