Skip to content

Commit 6545db6

Browse files
committed
added displayer for QueryRowsResult
1 parent c533641 commit 6545db6

File tree

1 file changed

+267
-2
lines changed

1 file changed

+267
-2
lines changed

scylla/src/transport/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)]
@@ -433,8 +435,271 @@ impl QueryRowsResult {
433435
Err(RowsError::TypeCheckFailed(err)) => Err(SingleRowError::TypeCheckFailed(err)),
434436
}
435437
}
438+
439+
pub fn rows_displayer<'a>(&'a self) -> RowsDisplayer<'a>
440+
{
441+
RowsDisplayer::new(self)
442+
}
436443
}
437444

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

0 commit comments

Comments
 (0)