From 293da8efc284f787bbad114d4460bc75aa3e7d77 Mon Sep 17 00:00:00 2001 From: cadl Date: Tue, 3 May 2022 16:24:22 +0800 Subject: [PATCH] feat(function): Use the "IEC 80000-13" to replace the decimal based unit kB/KB/MB always leads to a lot of misunderstandings, we just use the KiB --- .../tests/it/scalars/others/humanize.rs | 20 ++++++++-------- common/io/src/utils.rs | 11 ++++----- common/io/tests/it/utils.rs | 13 ++++++++--- .../120-other-functions/humanize-size.md | 8 +++---- .../02_0055_function_strings_humanize.result | 23 ++++++++++--------- .../02_0055_function_strings_humanize.sql | 21 +++++++++-------- 6 files changed, 51 insertions(+), 45 deletions(-) diff --git a/common/functions/tests/it/scalars/others/humanize.rs b/common/functions/tests/it/scalars/others/humanize.rs index cb5614c4569e..9d456c205bb5 100644 --- a/common/functions/tests/it/scalars/others/humanize.rs +++ b/common/functions/tests/it/scalars/others/humanize.rs @@ -22,27 +22,27 @@ use crate::scalars::scalar_function_test::ScalarFunctionTest; fn test_humanize_size_function() -> Result<()> { let tests = vec![ ScalarFunctionTest { - name: "humanize_size(1000)", - columns: vec![Series::from_data(vec![1000_u32])], - expect: Series::from_data(vec!["1 KB"]), + name: "humanize_size(1024)", + columns: vec![Series::from_data(vec![1024_u32])], + expect: Series::from_data(vec!["1.00 KiB"]), error: "", }, ScalarFunctionTest { - name: "humanize_size(-1000)", - columns: vec![Series::from_data(vec![-1000_i32])], - expect: Series::from_data(vec!["-1 KB"]), + name: "humanize_size(-1024)", + columns: vec![Series::from_data(vec![-1024_i32])], + expect: Series::from_data(vec!["-1.00 KiB"]), error: "", }, ScalarFunctionTest { name: "humanize_size('abc')", columns: vec![Series::from_data(vec!["abc"])], - expect: Series::from_data(vec!["-1 KB"]), + expect: Series::from_data(vec!["-1 KiB"]), error: "Expected a numeric type, but got String", }, ScalarFunctionTest { name: "humanize_size(true)", columns: vec![Series::from_data(vec![true])], - expect: Series::from_data(vec!["-1 KB"]), + expect: Series::from_data(vec!["-1 KiB"]), error: "Expected a numeric type, but got Boolean", }, ]; @@ -54,8 +54,8 @@ fn test_humanize_size_function() -> Result<()> { fn test_humanize_size_nullable() -> Result<()> { let tests = vec![ScalarFunctionTest { name: "humanize_size(null)", - columns: vec![Series::from_data(vec![Some(1_000_000_i32), None])], - expect: Series::from_data(vec![Some("1 MB"), None]), + columns: vec![Series::from_data(vec![Some(1_048_576_i32), None])], + expect: Series::from_data(vec![Some("1.00 MiB"), None]), error: "", }]; diff --git a/common/io/src/utils.rs b/common/io/src/utils.rs index 594a2067f585..dedd6a5e5452 100644 --- a/common/io/src/utils.rs +++ b/common/io/src/utils.rs @@ -22,19 +22,16 @@ use common_exception::Result; pub fn convert_byte_size(num: f64) -> String { let negative = if num.is_sign_positive() { "" } else { "-" }; let num = num.abs(); - let units = ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"]; + let units = ["B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"]; if num < 1_f64 { - return format!("{}{} {}", negative, num, "B"); + return format!("{}{:.02} {}", negative, num, "B"); } - let delimiter = 1000_f64; + let delimiter = 1024_f64; let exponent = cmp::min( (num.ln() / delimiter.ln()).floor() as i32, (units.len() - 1) as i32, ); - let pretty_bytes = format!("{:.2}", num / delimiter.powi(exponent)) - .parse::() - .unwrap() - * 1_f64; + let pretty_bytes = format!("{:.02}", num / delimiter.powi(exponent)); let unit = units[exponent as usize]; format!("{}{} {}", negative, pretty_bytes, unit) } diff --git a/common/io/tests/it/utils.rs b/common/io/tests/it/utils.rs index 03804b73857b..3f6e456f4564 100644 --- a/common/io/tests/it/utils.rs +++ b/common/io/tests/it/utils.rs @@ -16,9 +16,16 @@ use common_io::prelude::*; #[test] fn convert_test() { - assert_eq!(convert_byte_size(1_f64), "1 B"); - assert_eq!(convert_byte_size(1022_f64), "1.02 KB"); - assert_eq!(convert_byte_size(1022_f64 * 10000000f64), "10.22 GB"); + assert_eq!(convert_byte_size(0_f64), "0.00 B"); + assert_eq!(convert_byte_size(0.1_f64), "0.10 B"); + assert_eq!(convert_byte_size(1_f64), "1.00 B"); + assert_eq!(convert_byte_size(1023_f64), "1023.00 B"); + assert_eq!(convert_byte_size(1024_f64), "1.00 KiB"); + assert_eq!(convert_byte_size(1229_f64), "1.20 KiB"); + assert_eq!( + convert_byte_size(1024_f64 * 1024_f64 * 1024_f64), + "1.00 GiB" + ); assert_eq!(convert_number_size(1_f64), "1"); assert_eq!(convert_number_size(1022_f64), "1.02 thousand"); diff --git a/docs/doc/30-reference/20-functions/120-other-functions/humanize-size.md b/docs/doc/30-reference/20-functions/120-other-functions/humanize-size.md index 2578c9620f06..034779986354 100644 --- a/docs/doc/30-reference/20-functions/120-other-functions/humanize-size.md +++ b/docs/doc/30-reference/20-functions/120-other-functions/humanize-size.md @@ -2,7 +2,7 @@ title: HUMANIZE_SIZE --- -Returns the readable size with a suffix(KB, MB, etc). +Returns the readable size with a suffix(KiB, MiB, etc). ## Syntax @@ -24,10 +24,10 @@ String. ## Examples ```sql -SELECT HUMANIZE_SIZE(1000 * 1000) +SELECT HUMANIZE_SIZE(1024 * 1024) +-------------------------+ -| HUMANIZE_SIZE((1000 * 1000)) | +| HUMANIZE_SIZE((1024 * 1024)) | +-------------------------+ -| 1 MB | +| 1 MiB | +-------------------------+ ``` diff --git a/tests/suites/0_stateless/02_function/02_0055_function_strings_humanize.result b/tests/suites/0_stateless/02_function/02_0055_function_strings_humanize.result index 3d20294cfb83..1adcd56cad5a 100644 --- a/tests/suites/0_stateless/02_function/02_0055_function_strings_humanize.result +++ b/tests/suites/0_stateless/02_function/02_0055_function_strings_humanize.result @@ -1,14 +1,15 @@ -1 KB -1 MB -1 GB -1 TB -1 PB -1 EB -1 ZB -1 YB -1000 YB --1 KB -0 B +1.00 KiB +1.20 KiB +1.00 MiB +1.00 GiB +1.00 TiB +1.00 PiB +1.00 EiB +1.00 ZiB +1.00 YiB +1024.00 YiB +-1.00 KiB +0.00 B NULL 1 1 thousand diff --git a/tests/suites/0_stateless/02_function/02_0055_function_strings_humanize.sql b/tests/suites/0_stateless/02_function/02_0055_function_strings_humanize.sql index 2d5e3248a6c6..0dad64d84929 100644 --- a/tests/suites/0_stateless/02_function/02_0055_function_strings_humanize.sql +++ b/tests/suites/0_stateless/02_function/02_0055_function_strings_humanize.sql @@ -1,13 +1,14 @@ -SELECT HUMANIZE_SIZE(1000); -SELECT HUMANIZE_SIZE(1000000); -SELECT HUMANIZE_SIZE(1000000000); -SELECT HUMANIZE_SIZE(1000000000000); -SELECT HUMANIZE_SIZE(1000000000000000); -SELECT HUMANIZE_SIZE(1000000000000000000); -SELECT HUMANIZE_SIZE(1000000000000000000000); -SELECT HUMANIZE_SIZE(1000000000000000000000000); -SELECT HUMANIZE_SIZE(1000000000000000000000000000); -SELECT HUMANIZE_SIZE(-1000); +SELECT HUMANIZE_SIZE(1024); +SELECT HUMANIZE_SIZE(1229); +SELECT HUMANIZE_SIZE(POW(2, 20)); +SELECT HUMANIZE_SIZE(POW(2, 30)); +SELECT HUMANIZE_SIZE(POW(2, 40)); +SELECT HUMANIZE_SIZE(POW(2, 50)); +SELECT HUMANIZE_SIZE(POW(2, 60)); +SELECT HUMANIZE_SIZE(POW(2, 70)); +SELECT HUMANIZE_SIZE(POW(2, 80)); +SELECT HUMANIZE_SIZE(POW(2, 90)); +SELECT HUMANIZE_SIZE(-1024); SELECT HUMANIZE_SIZE(0); SELECT HUMANIZE_SIZE(NULL); SELECT HUMANIZE_NUMBER(1);