@@ -2,7 +2,8 @@ use std::fmt::Debug;
22use std:: fmt;
33use chrono:: { Duration , NaiveDate , NaiveTime , TimeZone , Utc } ;
44use 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 } ;
67use tabled:: { builder:: Builder , settings:: Style , settings:: themes:: Colorization , settings:: Color } ;
78
89use 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+
448483pub struct RowsDisplayer < ' a > {
449484 query_result : & ' a QueryRowsResult ,
450485 display_settings : RowsDisplayerSettings ,
451- terminal_width : usize ,
452486}
453487
454488impl < ' 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
560692struct WrapperDisplay < ' a , T : ' a > {
@@ -586,7 +718,6 @@ impl<'a> From<Box<dyn StringConvertible<'a>>> for String {
586718
587719impl < ' 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