Skip to content

Commit 66e012d

Browse files
committed
added doc strings for RowsDisplayerSettings and RowsDisplayer added methods for using colors and setting terminal width
1 parent f8458d6 commit 66e012d

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/transport/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;
@@ -445,10 +446,43 @@ impl QueryRowsResult {
445446
}
446447
}
447448

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

454488
impl<'a> RowsDisplayer<'a>
@@ -457,12 +491,15 @@ impl<'a> RowsDisplayer<'a>
457491
Self {
458492
query_result,
459493
display_settings: RowsDisplayerSettings::new(),
460-
terminal_width: 80,
461494
}
462495
}
463496

464497
pub fn set_terminal_width(&mut self, terminal_width: usize) {
465-
self.terminal_width = terminal_width;
498+
self.display_settings.terminal_width = terminal_width;
499+
}
500+
501+
pub fn use_color(&mut self, use_color: bool) {
502+
self.display_settings.print_in_color = use_color;
466503
}
467504

468505

@@ -555,6 +592,101 @@ impl<'a> RowsDisplayer<'a>
555592

556593
}
557594

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

560692
struct WrapperDisplay<'a, T: 'a>{
@@ -586,7 +718,6 @@ impl<'a> From<Box<dyn StringConvertible<'a>>> for String {
586718

587719
impl<'a> From<&dyn StringConvertible<'a>> for String {
588720
fn from(wrapper: &dyn StringConvertible<'a>) -> Self {
589-
// println!("before &dyn StringConvertible<'a>");
590721
wrapper.into()
591722
}
592723
}
@@ -597,7 +728,6 @@ where
597728
WrapperDisplay<'a, T>: fmt::Display,
598729
{
599730
fn from(wrapper: WrapperDisplay<'a, T>) -> Self {
600-
// println!("before WrapperDisplay<'a, T>");
601731
format!("{}", wrapper)
602732
}
603733
}
@@ -836,11 +966,9 @@ impl fmt::Display for WrapperDisplay<'_, CqlDate> {
836966
// around -250000-01-01 is the limit of naive date
837967

838968
let days = self.value.0 - magic_constant;
839-
println!("days: {}", days);
840969
let base_date = NaiveDate::from_ymd_opt(-250000, 1, 1).unwrap();
841970

842971
// Add the number of days
843-
println!("days as i64: {}", days as i64);
844972
let target_date = base_date + Duration::days(days as i64);
845973

846974
// Format the date
@@ -865,84 +993,6 @@ impl fmt::Display for WrapperDisplay<'_, std::net::IpAddr> {
865993
}
866994

867995

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

0 commit comments

Comments
 (0)