Skip to content

Commit

Permalink
Re-use decimal formatting
Browse files Browse the repository at this point in the history
  • Loading branch information
alippai committed Jun 12, 2021
1 parent be1a8fd commit c858052
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 32 deletions.
20 changes: 14 additions & 6 deletions arrow/src/array/array_binary.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@ use std::fmt;
use std::mem;
use std::{any::Any, iter::FromIterator};

use num::integer::div_rem;

use super::{
array::print_long_array, raw_pointer::RawPtrBox, Array, ArrayData,
FixedSizeListArray, GenericBinaryIter, GenericListArray, OffsetSizeTrait,
Expand Down Expand Up @@ -668,6 +666,17 @@ impl DecimalArray {
self.length * i as i32
}

#[inline(always)]
pub fn value_as_string(&self, row: usize) -> String {
let decimal_string = self.value(row).to_string();
if self.scale == 0 {
decimal_string
} else {
let splits = decimal_string.split_at(decimal_string.len() - self.scale);
format!("{}.{}", splits.0, splits.1)
}
}

pub fn from_fixed_size_list_array(
v: FixedSizeListArray,
precision: usize,
Expand Down Expand Up @@ -730,11 +739,10 @@ impl From<ArrayData> for DecimalArray {
impl fmt::Debug for DecimalArray {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "DecimalArray<{}, {}>\n[\n", self.precision, self.scale)?;
let point_index = 10_i128.pow(self.scale as u32);
print_long_array(self, f, |array, index, f| {
let (prefix, suffix) = &div_rem(array.value(index), point_index);
let formatted_decimal = array.value_as_string(index);

write!(f, "{}.{}", prefix, suffix.abs())
write!(f, "{}", formatted_decimal)
})?;
write!(f, "]")
}
Expand Down Expand Up @@ -1177,7 +1185,7 @@ mod tests {
decimal_builder.append_null().unwrap();
let arr = decimal_builder.finish();
assert_eq!(
"DecimalArray<23, 6>\n[\n 8887.0,\n -8887.0,\n null,\n]",
"DecimalArray<23, 6>\n[\n 8887.000000,\n -8887.000000,\n null,\n]",
format!("{:?}", arr)
);
}
Expand Down
13 changes: 2 additions & 11 deletions arrow/src/csv/writer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,14 +65,12 @@
//! }
//! ```
use std::convert::TryInto;
use std::io::Write;

use num::integer::div_rem;

use crate::datatypes::*;
use crate::error::{ArrowError, Result};
use crate::record_batch::RecordBatch;
use crate::util::display::make_string_from_decimal;
use crate::{array::*, util::serialization::lexical_to_string};
const DEFAULT_DATE_FORMAT: &str = "%F";
const DEFAULT_TIME_FORMAT: &str = "%T";
Expand Down Expand Up @@ -245,14 +243,7 @@ impl<W: Write> Writer<W> {
};
format!("{}", datetime.format(&self.timestamp_format))
}
DataType::Decimal(_precision, scale) => {
let c = col.as_any().downcast_ref::<DecimalArray>().unwrap();
let value = c.value(row_index);
let (prefix, suffix) =
div_rem(value, 10_i128.pow((*scale).try_into().unwrap()));

format!("{}.{}", prefix, suffix.abs())
}
DataType::Decimal(..) => make_string_from_decimal(col, row_index)?,
t => {
// List and Struct arrays not supported by the writer, any
// other type needs to be implemented
Expand Down
27 changes: 12 additions & 15 deletions arrow/src/util/display.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
//! purposes. See the `pretty` crate for additional functions for
//! record batch pretty printing.
use std::sync::Arc;

use crate::array::Array;
use crate::datatypes::{
ArrowNativeType, ArrowPrimitiveType, DataType, Int16Type, Int32Type, Int64Type,
Expand Down Expand Up @@ -192,18 +194,15 @@ macro_rules! make_string_from_list {
}};
}

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)
}};
#[inline(always)]
pub fn make_string_from_decimal(column: &Arc<dyn Array>, row: usize) -> Result<String> {
let array = column
.as_any()
.downcast_ref::<array::DecimalArray>()
.unwrap();

let formatted_decimal = array.value_as_string(row);
Ok(formatted_decimal)
}

/// Get the value at the given row in an array as a String.
Expand Down Expand Up @@ -231,9 +230,7 @@ pub fn array_value_to_string(column: &array::ArrayRef, row: usize) -> Result<Str
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::Decimal(..) => make_string_from_decimal(column, row),
DataType::Timestamp(unit, _) if *unit == TimeUnit::Second => {
make_string_datetime!(array::TimestampSecondArray, column, row)
}
Expand Down

0 comments on commit c858052

Please sign in to comment.