Skip to content

Commit 6a88e53

Browse files
committed
ci: make string format of decimal same with http handler.
1 parent 14cf166 commit 6a88e53

File tree

5 files changed

+37
-43
lines changed

5 files changed

+37
-43
lines changed

sql/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ arrow-buffer = { workspace = true }
2020
arrow-schema = { workspace = true }
2121
chrono = { workspace = true }
2222
chrono-tz = { workspace = true }
23+
ethnum = "1.5.1"
2324
databend-client = { workspace = true }
2425
jsonb = { workspace = true }
2526
tokio-stream = { workspace = true }

sql/src/value/arrow_decoder.rs

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -281,13 +281,17 @@ impl TryFrom<(&ArrowField, &Arc<dyn ArrowArray>, usize, Tz)> for Value {
281281
}
282282
ArrowDataType::Decimal256(p, s) => {
283283
match array.as_any().downcast_ref::<Decimal256Array>() {
284-
Some(array) => Ok(Value::Number(NumberValue::Decimal256(
285-
array.value(seq),
286-
DecimalSize {
287-
precision: *p,
288-
scale: *s as u8,
289-
},
290-
))),
284+
Some(array) => {
285+
let v = array.value(seq);
286+
let v: i256 = unsafe { std::mem::transmute(v) };
287+
Ok(Value::Number(NumberValue::Decimal256(
288+
v,
289+
DecimalSize {
290+
precision: *p,
291+
scale: *s as u8,
292+
},
293+
)))
294+
}
291295
None => Err(ConvertError::new("Decimal256", format!("{array:?}")).into()),
292296
}
293297
}

sql/src/value/base.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,10 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15-
use arrow_buffer::i256;
1615
use chrono::{DateTime, FixedOffset};
1716
use chrono_tz::Tz;
1817
use databend_client::schema::{DataType, DecimalDataType, DecimalSize, NumberDataType};
18+
use ethnum::i256;
1919

2020
// Thu 1970-01-01 is R.D. 719163
2121
pub(crate) const DAYS_FROM_CE: i32 = 719_163;

sql/src/value/format/display.rs

Lines changed: 20 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@
1515
use crate::_macro_internal::Value;
1616
use crate::value::base::{DAYS_FROM_CE, TIMESTAMP_FORMAT, TIMESTAMP_TIMEZONE_FORMAT};
1717
use crate::value::NumberValue;
18-
use arrow_buffer::i256;
1918
use chrono::NaiveDate;
19+
use ethnum::i256;
2020
use std::fmt::Write;
2121

2222
impl std::fmt::Display for Value {
@@ -180,39 +180,28 @@ pub fn display_decimal_128(num: i128, scale: u8) -> String {
180180
pub fn display_decimal_256(num: i256, scale: u8) -> String {
181181
let mut buf = String::new();
182182
if scale == 0 {
183-
write!(buf, "{num}").unwrap();
183+
write!(buf, "{}", num).unwrap();
184184
} else {
185-
let pow_scale = i256::from_i128(10i128).wrapping_pow(scale as u32);
186-
let width = scale as usize;
185+
let pow_scale = i256::from(10).pow(scale as u32);
187186
// -1/10 = 0
188-
let (int_part, neg) = if num >= i256::ZERO {
189-
(num / pow_scale, "")
187+
if !num.is_negative() {
188+
write!(
189+
buf,
190+
"{}.{:0>width$}",
191+
num / pow_scale,
192+
(num % pow_scale).wrapping_abs(),
193+
width = scale as usize
194+
)
190195
} else {
191-
(-num / pow_scale, "-")
192-
};
193-
let frac_part = (num % pow_scale).wrapping_abs();
194-
195-
match frac_part.to_i128() {
196-
Some(frac_part) => {
197-
write!(buf, "{neg}{int_part}.{frac_part:0>width$}").unwrap();
198-
}
199-
None => {
200-
// fractional part is too big for display,
201-
// split it into two parts.
202-
let pow = i256::from_i128(10i128).wrapping_pow(38);
203-
let frac_high_part = frac_part / pow;
204-
let frac_low_part = frac_part % pow;
205-
let frac_width = (scale - 38) as usize;
206-
207-
write!(
208-
buf,
209-
"{neg}{int_part}.{:0>frac_width$}{}",
210-
frac_high_part.to_i128().unwrap(),
211-
frac_low_part.to_i128().unwrap(),
212-
)
213-
.unwrap();
214-
}
196+
write!(
197+
buf,
198+
"-{}.{:0>width$}",
199+
-num / pow_scale,
200+
(num % pow_scale).wrapping_abs(),
201+
width = scale as usize
202+
)
215203
}
204+
.expect("display_decimal_256 should not fail");
216205
}
217-
buf
206+
String::from_utf8_lossy(buf.as_bytes()).to_string()
218207
}

sql/src/value/string_decoder.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,20 +12,20 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15+
use super::{NumberValue, Value, DAYS_FROM_CE, TIMESTAMP_TIMEZONE_FORMAT};
1516
use crate::_macro_internal::Error;
1617
use crate::cursor_ext::{
1718
collect_binary_number, collect_number, BufferReadStringExt, ReadBytesExt, ReadCheckPointExt,
1819
ReadNumberExt,
1920
};
2021
use crate::error::{ConvertError, Result};
21-
use arrow_buffer::i256;
2222
use chrono::{DateTime, Datelike, FixedOffset, LocalResult, NaiveDate, NaiveDateTime, TimeZone};
2323
use chrono_tz::Tz;
2424
use databend_client::schema::{DataType, DecimalDataType, DecimalSize, NumberDataType};
25+
use ethnum::i256;
2526
use hex;
2627
use std::io::{BufRead, Cursor};
27-
28-
use super::{NumberValue, Value, DAYS_FROM_CE, TIMESTAMP_TIMEZONE_FORMAT};
28+
use std::str::FromStr;
2929

3030
const NULL_VALUE: &str = "NULL";
3131
const TRUE_VALUE: &str = "1";
@@ -515,7 +515,7 @@ fn parse_decimal(text: &str, size: DecimalSize) -> Result<NumberValue> {
515515
let digits = unsafe { std::str::from_utf8_unchecked(&digits[..precision]) };
516516

517517
let result = if size.precision > 38 {
518-
NumberValue::Decimal256(i256::from_string(digits).unwrap(), size)
518+
NumberValue::Decimal256(i256::from_str(digits).unwrap(), size)
519519
} else {
520520
NumberValue::Decimal128(digits.parse::<i128>()?, size)
521521
};

0 commit comments

Comments
 (0)