Skip to content

Commit 93614b8

Browse files
committed
added doc strings for RowsDisplayerSettings and RowsDisplayer added methods for using colors and setting terminal width
1 parent a0317ae commit 93614b8

File tree

2 files changed

+143
-92
lines changed

2 files changed

+143
-92
lines changed

examples/displayer.rs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,6 @@ async fn main() -> Result<()> {
7777
)
7878
.await?;
7979

80-
println!("Created table examples_ks.basic2");
8180
session
8281
.query_unpaged(
8382
"INSERT INTO examples_ks.basic4
@@ -87,9 +86,6 @@ async fn main() -> Result<()> {
8786
&[],
8887
)
8988
.await?;
90-
println!("insert1 done");
91-
92-
println!("SELECT * FROM examples_ks.basic2");
9389

9490
let result2 : QueryRowsResult= session
9591
.query_unpaged("SELECT * FROM examples_ks.basic4", &[])
@@ -134,7 +130,7 @@ async fn main() -> Result<()> {
134130
"INSERT INTO examples_ks.basic6
135131
(a, timud, date1, ipaddr, dur)
136132
VALUES
137-
(4, NOW(), '2024-01-15', '192.168.0.14', 13y2w89h4m48s137ms);", // cqlsh prints this as 89.08003805555556h4.8022833333333335m48.137s137.0ms
133+
(4, NOW(), '2024-01-15', '192.168.0.14', 13y2w89h4m48s137ms);",
138134
&[],
139135
)
140136
.await?;
@@ -160,8 +156,13 @@ async fn main() -> Result<()> {
160156
.await?
161157
.into_rows_result()?;
162158

163-
let displayer = result2.rows_displayer();
159+
let mut displayer = result2.rows_displayer();
164160
println!("DISPLAYER:");
165161
println!("{}", displayer);
162+
163+
displayer.set_terminal_width(80);
164+
displayer.use_color(false);
165+
println!("DISPLAYER no color, width = 80:");
166+
println!("{}", displayer);
166167
Ok(())
167168
}

scylla/src/response/query_result.rs

Lines changed: 136 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ use std::fmt::Debug;
22
use std::fmt;
33
use chrono::{Duration, NaiveDate, NaiveTime, TimeZone, Utc};
44
use scylla_cql::frame::value::{CqlDate, CqlDecimal, CqlDuration, CqlTime, CqlTimestamp, CqlTimeuuid};
5-
use tabled::settings::Alignment;
5+
use tabled::settings::peaker::Priority;
6+
use tabled::settings::{Alignment, Width};
67
use tabled::{builder::Builder, settings::Style, settings::themes::Colorization, settings::Color};
78

89
use thiserror::Error;
@@ -456,10 +457,43 @@ impl QueryRowsResult {
456457
}
457458
}
458459

460+
/// A utility struct for displaying rows received from the database in a [`QueryRowsResult`].
461+
///
462+
/// This struct provides methods to configure the display settings and format the rows
463+
/// as a table for easier visualization. It supports various display settings such as
464+
/// terminal width, color usage, and formatting of different CQL value types.
465+
///
466+
/// # Example
467+
///
468+
/// ```rust
469+
/// # use scylla::transport::query_result::{QueryResult, QueryRowsResult, RowsDisplayer};
470+
/// # fn example(query_result: QueryResult) -> Result<(), Box<dyn std::error::Error>> {
471+
/// let rows_result = query_result.into_rows_result()?;
472+
/// let mut displayer = RowsDisplayer::new(&rows_result);
473+
/// displayer.set_terminal_width(80);
474+
/// displayer.use_color(true);
475+
/// println!("{}", displayer);
476+
/// # Ok(())
477+
/// # }
478+
/// ```
479+
///
480+
/// # Methods
481+
///
482+
/// - `new(query_result: &'a QueryRowsResult) -> Self`
483+
/// Creates a new `RowsDisplayer` for the given `QueryRowsResult`.
484+
///
485+
/// - `set_terminal_width(&mut self, terminal_width: usize)`
486+
/// Sets the terminal width for wrapping the table output.
487+
///
488+
/// - `use_color(&mut self, use_color: bool)`
489+
/// Enables or disables color in the table output.
490+
///
491+
/// - `fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result`
492+
/// Formats the rows as a table and writes it to the given formatter.
493+
459494
pub struct RowsDisplayer<'a> {
460495
query_result: &'a QueryRowsResult,
461496
display_settings: RowsDisplayerSettings,
462-
terminal_width: usize,
463497
}
464498

465499
impl<'a> RowsDisplayer<'a>
@@ -468,12 +502,15 @@ impl<'a> RowsDisplayer<'a>
468502
Self {
469503
query_result,
470504
display_settings: RowsDisplayerSettings::new(),
471-
terminal_width: 80,
472505
}
473506
}
474507

475508
pub fn set_terminal_width(&mut self, terminal_width: usize) {
476-
self.terminal_width = terminal_width;
509+
self.display_settings.terminal_width = terminal_width;
510+
}
511+
512+
pub fn use_color(&mut self, use_color: bool) {
513+
self.display_settings.print_in_color = use_color;
477514
}
478515

479516

@@ -566,6 +603,101 @@ impl<'a> RowsDisplayer<'a>
566603

567604
}
568605

606+
impl fmt::Display for RowsDisplayer<'_> {
607+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
608+
let row_iter : TypedRowIterator<'_, '_, Row> = match self.query_result.rows::<Row>(){
609+
Ok(row_iter) => row_iter,
610+
Err(_) => return write!(f, "Error"),
611+
};
612+
613+
// put columns names to the table
614+
let column_names : Vec<&str> = self.query_result.column_specs().iter().map(|column_spec| column_spec.name()).collect();
615+
let mut builder: Builder = Builder::new();
616+
builder.push_record(column_names);
617+
618+
// put rows to the table
619+
for row_result in row_iter {
620+
let row_result : Row = match row_result {
621+
Ok(row_result) => row_result,
622+
Err(_) => return write!(f, "Error"),
623+
};
624+
let columns : Vec<std::option::Option<CqlValue>> = row_result.columns;
625+
let mut row_values: Vec<Box<dyn StringConvertible>> = Vec::new();
626+
for item in &columns {
627+
let wrapper = self.get_item_wrapper(item);
628+
row_values.push(wrapper);
629+
}
630+
builder.push_record(row_values);
631+
}
632+
633+
let mut table = builder.build();
634+
635+
let mut table = table.with(Style::psql());
636+
table = table.with(Alignment::right());
637+
if self.display_settings.terminal_width != 0 {
638+
table = table.with( Width::wrap(self.display_settings.terminal_width).priority(Priority::max(true)));
639+
}
640+
641+
if self.display_settings.print_in_color {
642+
let colum_colors: Vec<Color> = self.query_result.column_specs().iter().map(|column_spec|
643+
if *column_spec.typ() == ColumnType::Text{
644+
Color::FG_YELLOW
645+
}
646+
else if *column_spec.typ() == ColumnType::Blob{
647+
Color::FG_MAGENTA
648+
}
649+
else {
650+
Color::FG_GREEN
651+
}
652+
).collect();
653+
654+
table = table.with(Colorization::columns(colum_colors))
655+
.with(Colorization::exact([Color::FG_MAGENTA], tabled::settings::object::Rows::first()));
656+
}
657+
658+
write!(f, "{}", table)
659+
}
660+
}
661+
662+
663+
664+
/// Settings for displaying rows in a `RowsDisplayer`.
665+
///
666+
/// This struct holds various configuration options for formatting and displaying
667+
/// rows received from the database. It includes settings for byte display format,
668+
/// exponent display for floats and integers, precision for doubles, color usage,
669+
/// and terminal width for wrapping the table output.
670+
struct RowsDisplayerSettings {
671+
byte_displaying: ByteDisplaying, // for blobs
672+
exponent_displaying_floats: bool, // for floats
673+
exponent_displaying_integers: bool, // for integers
674+
double_precision: usize, // for doubles
675+
print_in_color: bool,
676+
terminal_width: usize,
677+
}
678+
679+
impl RowsDisplayerSettings {
680+
fn new() -> Self { // TODO write Default trait
681+
Self {
682+
byte_displaying: ByteDisplaying::Hex,
683+
exponent_displaying_floats: false,
684+
exponent_displaying_integers: false,
685+
double_precision: 5,
686+
print_in_color: true,
687+
terminal_width: 0,
688+
}
689+
}
690+
}
691+
692+
693+
694+
#[derive(PartialEq)]
695+
enum ByteDisplaying {
696+
Ascii,
697+
Hex,
698+
Dec,
699+
}
700+
569701
// wrappers for scylla datatypes implementing Display
570702

571703
struct WrapperDisplay<'a, T: 'a>{
@@ -597,7 +729,6 @@ impl<'a> From<Box<dyn StringConvertible<'a>>> for String {
597729

598730
impl<'a> From<&dyn StringConvertible<'a>> for String {
599731
fn from(wrapper: &dyn StringConvertible<'a>) -> Self {
600-
// println!("before &dyn StringConvertible<'a>");
601732
wrapper.into()
602733
}
603734
}
@@ -608,7 +739,6 @@ where
608739
WrapperDisplay<'a, T>: fmt::Display,
609740
{
610741
fn from(wrapper: WrapperDisplay<'a, T>) -> Self {
611-
// println!("before WrapperDisplay<'a, T>");
612742
format!("{}", wrapper)
613743
}
614744
}
@@ -847,11 +977,9 @@ impl fmt::Display for WrapperDisplay<'_, CqlDate> {
847977
// around -250000-01-01 is the limit of naive date
848978

849979
let days = self.value.0 - magic_constant;
850-
println!("days: {}", days);
851980
let base_date = NaiveDate::from_ymd_opt(-250000, 1, 1).unwrap();
852981

853982
// Add the number of days
854-
println!("days as i64: {}", days as i64);
855983
let target_date = base_date + Duration::days(days as i64);
856984

857985
// Format the date
@@ -876,84 +1004,6 @@ impl fmt::Display for WrapperDisplay<'_, std::net::IpAddr> {
8761004
}
8771005

8781006

879-
880-
881-
impl fmt::Display for RowsDisplayer<'_> {
882-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
883-
let row_iter : TypedRowIterator<'_, '_, Row> = match self.query_result.rows::<Row>(){
884-
Ok(row_iter) => row_iter,
885-
Err(_) => return write!(f, "Error"),
886-
};
887-
888-
// put columns names to the table
889-
let column_names : Vec<&str> = self.query_result.column_specs().iter().map(|column_spec| column_spec.name()).collect();
890-
let mut builder: Builder = Builder::new();
891-
builder.push_record(column_names);
892-
893-
// put rows to the table
894-
for row_result in row_iter {
895-
// println!("row");
896-
let row_result : Row = match row_result {
897-
Ok(row_result) => row_result,
898-
Err(_) => return write!(f, "Error"),
899-
};
900-
let columns : Vec<std::option::Option<CqlValue>> = row_result.columns;
901-
let mut row_values: Vec<Box<dyn StringConvertible>> = Vec::new();
902-
for item in &columns {
903-
let wrapper = self.get_item_wrapper(item);
904-
row_values.push(wrapper);
905-
}
906-
builder.push_record(row_values);
907-
}
908-
909-
// write table to the formatter
910-
let mut table = builder.build();
911-
table.with(Style::psql())
912-
// Width::wrap(self.terminal_width).priority(Priority::max(true)),
913-
.with(Colorization::columns([Color::FG_GREEN]))
914-
.with(Colorization::exact([Color::FG_MAGENTA], tabled::settings::object::Rows::first()))
915-
.with(Alignment::right());
916-
917-
write!(f, "{}", table)
918-
}
919-
}
920-
921-
struct RowsDisplayerSettings {
922-
byte_displaying: ByteDisplaying, // for blobs
923-
exponent_displaying_floats: bool, // for floats
924-
exponent_displaying_integers: bool, // for integers
925-
double_precision: usize, // for doubles
926-
}
927-
928-
impl RowsDisplayerSettings {
929-
fn new() -> Self { // TODO write Default trait
930-
Self {
931-
byte_displaying: ByteDisplaying::Hex,
932-
exponent_displaying_floats: false,
933-
exponent_displaying_integers: false,
934-
double_precision: 5,
935-
}
936-
}
937-
938-
fn set_byte_displaying(&mut self, byte_displaying: ByteDisplaying) {
939-
self.byte_displaying = byte_displaying;
940-
}
941-
942-
fn set_exponent_displaying_floats(&mut self, exponent_displaying_floats: bool) {
943-
self.exponent_displaying_floats = exponent_displaying_floats;
944-
}
945-
946-
fn set_exponent_displaying_integers(&mut self, exponent_displaying_integers: bool) {
947-
self.exponent_displaying_integers = exponent_displaying_integers;
948-
}
949-
}
950-
951-
#[derive(PartialEq)]
952-
enum ByteDisplaying {
953-
Ascii,
954-
Hex,
955-
Dec,
956-
}
9571007
/// An error returned by [`QueryResult::into_rows_result`]
9581008
///
9591009
/// The `ResultNotRows` variant contains original [`QueryResult`],

0 commit comments

Comments
 (0)