Added Decimal support to pretty-print display utility (#230) (#273)
* Added Decimal support to pretty-print display utility (#230)
* Applied cargo fmt to fix linting errors
* Added proper printing for decimals based on scale, moved tests to pretty.rs
* Applied cargo fmt on pretty test
Co-authored-by: Manish Gill <manish.gill@tomtom.com>
diff --git a/arrow/src/util/display.rs b/arrow/src/util/display.rs
index e40abab..61f549a 100644
--- a/arrow/src/util/display.rs
+++ b/arrow/src/util/display.rs
@@ -192,6 +192,20 @@
}};
}
+macro_rules! make_string_from_decimal {
+ ($array_type: ty, $column: ident, $row: ident, $scale: ident) => {{
+ let array = $column.as_any().downcast_ref::<$array_type>().unwrap();
+ let decimal_string = array.value($row).to_string();
+ let formatted_decimal = if *$scale == 0 {
+ decimal_string
+ } else {
+ let splits = decimal_string.split_at(decimal_string.len() - *$scale);
+ format!("{}.{}", splits.0, splits.1)
+ };
+ Ok(formatted_decimal)
+ }};
+}
+
/// Get the value at the given row in an array as a String.
///
/// Note this function is quite inefficient and is unlikely to be
@@ -217,6 +231,9 @@
DataType::Float16 => make_string!(array::Float32Array, column, row),
DataType::Float32 => make_string!(array::Float32Array, column, row),
DataType::Float64 => make_string!(array::Float64Array, column, row),
+ DataType::Decimal(_, scale) => {
+ make_string_from_decimal!(array::DecimalArray, column, row, scale)
+ }
DataType::Timestamp(unit, _) if *unit == TimeUnit::Second => {
make_string_datetime!(array::TimestampSecondArray, column, row)
}
diff --git a/arrow/src/util/pretty.rs b/arrow/src/util/pretty.rs
index f354899..d307406 100644
--- a/arrow/src/util/pretty.rs
+++ b/arrow/src/util/pretty.rs
@@ -115,6 +115,7 @@
};
use super::*;
+ use crate::array::{DecimalBuilder, Int32Array};
use std::sync::Arc;
#[test]
@@ -418,4 +419,92 @@
];
check_datetime!(Time64NanosecondArray, 11111111, expected);
}
+
+ #[test]
+ fn test_int_display() -> Result<()> {
+ let array = Arc::new(Int32Array::from(vec![6, 3])) as ArrayRef;
+ let actual_one = array_value_to_string(&array, 0).unwrap();
+ let expected_one = "6";
+
+ let actual_two = array_value_to_string(&array, 1).unwrap();
+ let expected_two = "3";
+ assert_eq!(actual_one, expected_one);
+ assert_eq!(actual_two, expected_two);
+ Ok(())
+ }
+
+ #[test]
+ fn test_decimal_display() -> Result<()> {
+ let capacity = 10;
+ let precision = 10;
+ let scale = 2;
+
+ let mut builder = DecimalBuilder::new(capacity, precision, scale);
+ builder.append_value(101).unwrap();
+ builder.append_null().unwrap();
+ builder.append_value(200).unwrap();
+ builder.append_value(3040).unwrap();
+
+ let dm = Arc::new(builder.finish()) as ArrayRef;
+
+ let schema = Arc::new(Schema::new(vec![Field::new(
+ "f",
+ dm.data_type().clone(),
+ true,
+ )]));
+
+ let batch = RecordBatch::try_new(schema, vec![dm])?;
+
+ let table = pretty_format_batches(&[batch])?;
+
+ let expected = vec![
+ "+-------+",
+ "| f |",
+ "+-------+",
+ "| 1.01 |",
+ "| |",
+ "| 2.00 |",
+ "| 30.40 |",
+ "+-------+",
+ ];
+
+ let actual: Vec<&str> = table.lines().collect();
+ assert_eq!(expected, actual, "Actual result:\n{}", table);
+
+ Ok(())
+ }
+
+ #[test]
+ fn test_decimal_display_zero_scale() -> Result<()> {
+ let capacity = 10;
+ let precision = 5;
+ let scale = 0;
+
+ let mut builder = DecimalBuilder::new(capacity, precision, scale);
+ builder.append_value(101).unwrap();
+ builder.append_null().unwrap();
+ builder.append_value(200).unwrap();
+ builder.append_value(3040).unwrap();
+
+ let dm = Arc::new(builder.finish()) as ArrayRef;
+
+ let schema = Arc::new(Schema::new(vec![Field::new(
+ "f",
+ dm.data_type().clone(),
+ true,
+ )]));
+
+ let batch = RecordBatch::try_new(schema, vec![dm])?;
+
+ let table = pretty_format_batches(&[batch])?;
+ let expected = vec![
+ "+------+", "| f |", "+------+", "| 101 |", "| |", "| 200 |",
+ "| 3040 |", "+------+",
+ ];
+
+ let actual: Vec<&str> = table.lines().collect();
+ assert_eq!(expected, actual, "Actual result:\n{}", table);
+
+ Ok(())
+ }
}