Skip to content

Commit 3bbba59

Browse files
committed
added displayer for QueryRowsResult
1 parent 77ea092 commit 3bbba59

File tree

1 file changed

+267
-2
lines changed

1 file changed

+267
-2
lines changed

scylla/src/response/query_result.rs

Lines changed: 267 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
11
use std::fmt::Debug;
2+
use std::fmt;
3+
use tabled::{builder::Builder, settings::Style};
24

35
use thiserror::Error;
46
use uuid::Uuid;
57

68
use scylla_cql::frame::frame_errors::ResultMetadataAndRowsCountParseError;
79
use scylla_cql::frame::response::result::{
8-
ColumnSpec, ColumnType, DeserializedMetadataAndRawRows, RawMetadataAndRawRows, Row, TableSpec,
10+
ColumnSpec, ColumnType, CqlValue, DeserializedMetadataAndRawRows, RawMetadataAndRawRows, Row, TableSpec
911
};
1012
use scylla_cql::types::deserialize::result::TypedRowIterator;
11-
use scylla_cql::types::deserialize::row::DeserializeRow;
13+
use scylla_cql::types::deserialize::row::{self, DeserializeRow};
1214
use scylla_cql::types::deserialize::{DeserializationError, TypeCheckError};
1315

1416
#[allow(deprecated)]
@@ -444,8 +446,271 @@ impl QueryRowsResult {
444446

445447
(raw_rows_with_metadata, tracing_id, warnings)
446448
}
449+
450+
pub fn rows_displayer<'a>(&'a self) -> RowsDisplayer<'a>
451+
{
452+
RowsDisplayer::new(self)
453+
}
447454
}
448455

456+
pub struct RowsDisplayer<'a> {
457+
query_result: &'a QueryRowsResult,
458+
display_settings: RowsDisplayerSettings,
459+
}
460+
461+
impl<'a> RowsDisplayer<'a>
462+
{
463+
pub fn new(query_result: &'a QueryRowsResult) -> Self {
464+
Self {
465+
query_result,
466+
display_settings: RowsDisplayerSettings::new(),
467+
}
468+
}
469+
470+
pub fn display(self) {
471+
let row_iter : TypedRowIterator<'_, '_, Row> = match self.query_result.rows::<Row>(){
472+
Ok(row_iter) => row_iter,
473+
Err(_) => return,
474+
};
475+
476+
let column_names : Vec<&str> = self.query_result.column_specs().iter().map(|column_spec| column_spec.name()).collect();
477+
let mut builder: Builder = Builder::new();
478+
builder.push_record(column_names);
479+
480+
for row_result in row_iter {
481+
let row_result : Row = match row_result {
482+
Ok(row_result) => row_result,
483+
Err(_) => return,
484+
};
485+
let columns : Vec<std::option::Option<CqlValue>> = row_result.columns;
486+
let mut row_values : Vec<String> = Vec::new();
487+
for column in columns {
488+
let item_string = self.get_item_string(column);
489+
row_values.push(item_string);
490+
}
491+
builder.push_record(row_values);
492+
493+
}
494+
let mut table = builder.build();
495+
table.with(Style::ascii_rounded());
496+
println!("{}", table.to_string());
497+
498+
}
499+
500+
fn get_item_string(&self, column: std::option::Option<CqlValue>) -> String {
501+
match column {
502+
Some(CqlValue::Ascii(value)) => {
503+
return format!("{}", value);
504+
},
505+
Some(CqlValue::BigInt(value)) => {
506+
self.int64_to_string(value)
507+
},
508+
Some(CqlValue::Blob(value)) => {
509+
self.blob_to_string(value)
510+
},
511+
Some(CqlValue::Boolean(value)) => {
512+
return format!("{}", value);
513+
},
514+
Some(CqlValue::Counter(value)) => {
515+
return format!("{:?}", value);
516+
},
517+
Some(CqlValue::Decimal(value)) => {
518+
return format!("{:?}", value);
519+
},
520+
Some(CqlValue::Double(value)) => { // TODO set formating for real numbers
521+
return format!("{}", value);
522+
},
523+
Some(CqlValue::Float(value)) => {
524+
self.float_to_string(value)
525+
},
526+
Some(CqlValue::Int(value)) => { // TODO set formating for integers
527+
return self.int32_to_string(value);
528+
},
529+
Some(CqlValue::Text(value)) => {
530+
return format!("{}", value);
531+
},
532+
Some(CqlValue::Timestamp(value)) => { // TOOD set formating for timestamp
533+
return format!("{:?}", value);
534+
},
535+
Some(CqlValue::Uuid(value)) => {
536+
return format!("{}", value);
537+
},
538+
Some(CqlValue::Inet(value)) => {
539+
return format!("{}", value);
540+
},
541+
Some(CqlValue::List(value)) => { // TODO set formating for list
542+
return format!("{:?}", value);
543+
},
544+
Some(CqlValue::Map(value)) => { // TODO set formating for map
545+
return format!("{:?}", value);
546+
},
547+
Some(CqlValue::Set(value)) => { // TODO set formating for set
548+
return format!("{:?}", value);
549+
},
550+
Some(CqlValue::UserDefinedType { keyspace, type_name, fields }) => { // Idk what to do with this
551+
return format!("UserDefinedType: keyspace: {}, type_name: {}, fields: {:?}", keyspace, type_name, fields);
552+
},
553+
Some(CqlValue::Tuple(value)) => { // TODO set formating for tuple
554+
return format!("{:?}", value);
555+
},
556+
Some(CqlValue::Date(value)) => { // TODO set formating for date
557+
return format!("Date: {:?}", value);
558+
},
559+
Some(CqlValue::Duration(value)) => {
560+
return format!("Duration: {:?}", value);
561+
},
562+
Some(CqlValue::Empty) => {
563+
return format!("Empty");
564+
},
565+
Some(CqlValue::SmallInt(value)) => {
566+
self.int16_to_string(value)
567+
},
568+
Some(CqlValue::TinyInt(value)) => {
569+
self.int8_to_string(value)
570+
},
571+
Some(CqlValue::Varint(value)) => {
572+
return format!("{:?}", value);
573+
},
574+
Some(CqlValue::Time(value)) => {
575+
return format!("{:?}", value);
576+
},
577+
Some(CqlValue::Timeuuid(value)) => {
578+
return format!("{:?}", value);
579+
},
580+
None => {
581+
return format!("None");
582+
},
583+
}
584+
}
585+
586+
fn blob_to_string(&self, blob: Vec<u8>) -> String {
587+
let mut result = String::new();
588+
for byte in blob {
589+
match self.display_settings.byte_displaying {
590+
ByteDisplaying::Ascii => {
591+
result.push_str(&format!("{}", byte as char));
592+
},
593+
ByteDisplaying::Hex => {
594+
result.push_str(&format!("{:02x}", byte));
595+
},
596+
ByteDisplaying::Dec => {
597+
result.push_str(&format!("{}", byte));
598+
},
599+
}
600+
}
601+
return result;
602+
}
603+
604+
fn float_to_string(&self, float: f32) -> String {
605+
if self.display_settings.exponent_displaying_floats {
606+
return format!("{:e}", float);
607+
} else {
608+
return format!("{}", float);
609+
}
610+
}
611+
612+
fn int64_to_string(&self, int: i64) -> String {
613+
if self.display_settings.exponent_displaying_integers {
614+
return format!("{:e}", int);
615+
} else {
616+
return format!("{}", int);
617+
}
618+
}
619+
620+
fn int32_to_string(&self, int: i32) -> String {
621+
if self.display_settings.exponent_displaying_integers {
622+
return format!("{:e}", int);
623+
} else {
624+
return format!("{}", int);
625+
}
626+
}
627+
628+
fn int16_to_string(&self, int: i16) -> String {
629+
if self.display_settings.exponent_displaying_integers {
630+
return format!("{:e}", int);
631+
} else {
632+
return format!("{}", int);
633+
}
634+
}
635+
636+
fn int8_to_string(&self, int: i8) -> String {
637+
if self.display_settings.exponent_displaying_integers {
638+
return format!("{:e}", int);
639+
} else {
640+
return format!("{}", int);
641+
}
642+
}
643+
644+
645+
}
646+
647+
impl fmt::Display for RowsDisplayer<'_> {
648+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
649+
let row_iter : TypedRowIterator<'_, '_, Row> = match self.query_result.rows::<Row>(){
650+
Ok(row_iter) => row_iter,
651+
Err(_) => return write!(f, "Error"),
652+
};
653+
654+
// put columns names to the table
655+
let column_names : Vec<&str> = self.query_result.column_specs().iter().map(|column_spec| column_spec.name()).collect();
656+
let mut builder: Builder = Builder::new();
657+
builder.push_record(column_names);
658+
659+
// put rows to the table
660+
for row_result in row_iter {
661+
let row_result : Row = match row_result {
662+
Ok(row_result) => row_result,
663+
Err(_) => return write!(f, "Error"),
664+
};
665+
let columns : Vec<std::option::Option<CqlValue>> = row_result.columns;
666+
let mut row_values : Vec<String> = Vec::new();
667+
for column in columns {
668+
let item_string = self.get_item_string(column);
669+
row_values.push(item_string);
670+
}
671+
builder.push_record(row_values);
672+
}
673+
674+
// write table to the formatter
675+
let mut table = builder.build();
676+
table.with(Style::modern_rounded());
677+
write!(f, "{}", table)
678+
}
679+
}
680+
681+
struct RowsDisplayerSettings {
682+
byte_displaying: ByteDisplaying, // for blobs
683+
exponent_displaying_floats: bool, // for floats
684+
exponent_displaying_integers: bool, // for integers
685+
}
686+
687+
impl RowsDisplayerSettings {
688+
fn new() -> Self {
689+
Self {
690+
byte_displaying: ByteDisplaying::Ascii,
691+
exponent_displaying_floats: false,
692+
exponent_displaying_integers: false,
693+
}
694+
}
695+
696+
fn set_byte_displaying(&mut self, byte_displaying: ByteDisplaying) {
697+
self.byte_displaying = byte_displaying;
698+
}
699+
700+
fn set_exponent_displaying_floats(&mut self, exponent_displaying_floats: bool) {
701+
self.exponent_displaying_floats = exponent_displaying_floats;
702+
}
703+
704+
fn set_exponent_displaying_integers(&mut self, exponent_displaying_integers: bool) {
705+
self.exponent_displaying_integers = exponent_displaying_integers;
706+
}
707+
}
708+
709+
enum ByteDisplaying {
710+
Ascii,
711+
Hex,
712+
Dec,
713+
}
449714
/// An error returned by [`QueryResult::into_rows_result`]
450715
///
451716
/// The `ResultNotRows` variant contains original [`QueryResult`],

0 commit comments

Comments
 (0)