Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ clap = { version = "4.5", features = ["derive", "env"] }
comfy-table = "7.1"
csv = "1.3"
ctrlc = { version = "3.4.6", features = ["termination"] }
databend-common-ast = "0.2.3"
databend-common-ast = "0.2.4"
dirs = "5.0"
fern = { version = "0.7", features = ["colored"] }
indicatif = "0.18.3"
Expand Down
6 changes: 5 additions & 1 deletion cli/src/display.rs
Original file line number Diff line number Diff line change
Expand Up @@ -593,7 +593,7 @@ fn create_table(
&& results[0].values().iter().all(|v| {
if matches!(v, Value::Number(_)) {
let f: f64 = v.to_string().parse().unwrap();
f >= 1_000_000f64
(1_000_000f64..=1e+21f64).contains(&f)
} else {
false
}
Expand Down Expand Up @@ -720,6 +720,7 @@ fn format_table_style(
) -> Cell {
let is_null = matches!(value, Value::Null);
let is_string = matches!(value, Value::String(_));
let is_number = matches!(value, Value::Number(_));
let mut value_str = value.to_string();
if is_string && quote_string {
let mut escaped_value_str = String::with_capacity(value_str.len());
Expand All @@ -737,6 +738,9 @@ fn format_table_style(
value_str = escaped_value_str;
}
value_str = truncate_string(value_str, max_col_width);
if !is_number {
value_str = truncate_string(value_str, max_col_width);
}
if is_string && quote_string {
value_str = format!("'{value_str}'");
}
Expand Down
1 change: 1 addition & 0 deletions cli/tests/00-base.result
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ aa
"def add(a, b):
a + b"
3.00 3.00 0.0000000170141183460469231731687303715884105727000 -0.0000000170141183460469231731687303715884105727000
1.0234567899999998e+81 1.2345678901234568e-11 NaN inf
Asia/Shanghai
3
0 0.00
Expand Down
1 change: 1 addition & 0 deletions cli/tests/00-base.sql
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ select 'in comment block';
*/

select 1.00 + 2.00, 3.00, 0.0000000170141183460469231731687303715884105727000, -0.0000000170141183460469231731687303715884105727000;
select 10.234567899999999e80, 1234567890123456789012345678901234567890123456789012345678901234567890.1e-80, CAST('NaN' AS FLOAT), CAST('inf' AS DOUBLE);

select/*+ SET_VAR(timezone='Asia/Shanghai') */ timezone();

Expand Down
1 change: 1 addition & 0 deletions sql/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,4 @@ jiff = { workspace = true }
serde = { version = "1.0", default-features = false, features = ["derive"] }
serde_json = { version = "1.0", default-features = false, features = ["std", "raw_value"] }
url = { version = "2.5", default-features = false }
zmij = "1.0"
28 changes: 22 additions & 6 deletions sql/src/cursor_ext/cursor_read_number_ext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,17 @@ pub fn collect_number(buffer: &[u8]) -> (usize, usize) {
(index, effective)
}

fn collect_special_float(buffer: &[u8]) -> Option<usize> {
const SPECIAL_FLOATS: [&[u8]; 5] = [b"infinity", b"-infinity", b"inf", b"-inf", b"nan"];

for literal in SPECIAL_FLOATS {
if buffer.len() >= literal.len() && buffer[..literal.len()].eq_ignore_ascii_case(literal) {
return Some(literal.len());
}
}
None
}

#[inline]
fn read_num_text_exact<T: FromLexical>(buf: &[u8]) -> Result<T> {
match FromLexical::from_lexical(buf) {
Expand Down Expand Up @@ -135,12 +146,17 @@ where

fn read_float_text<T: FromLexical>(&mut self) -> Result<T> {
let buf = self.fill_buf()?;
let (n_in, n_out) = collect_number(buf);
if n_in == 0 {
return Err(std::io::Error::new(
ErrorKind::InvalidData,
"Unable to parse float: provided text is not in a recognizable floating-point format.".to_string()
));
let (mut n_in, mut n_out) = collect_number(buf);
if n_in == 0 || (n_in == 1 && buf.first() == Some(&b'-')) {
if let Some(n_special) = collect_special_float(buf) {
n_in = n_special;
n_out = n_special;
} else {
return Err(std::io::Error::new(
ErrorKind::InvalidData,
"Unable to parse float: provided text is not in a recognizable floating-point format.".to_string()
));
}
}
let buf = self.fill_buf()?;
let n = read_num_text_exact(&buf[..n_out])?;
Expand Down
60 changes: 57 additions & 3 deletions sql/src/value/format/display.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ impl std::fmt::Display for NumberValue {
NumberValue::UInt16(i) => write!(f, "{i}"),
NumberValue::UInt32(i) => write!(f, "{i}"),
NumberValue::UInt64(i) => write!(f, "{i}"),
NumberValue::Float32(i) => write!(f, "{i}"),
NumberValue::Float64(i) => write!(f, "{i}"),
NumberValue::Float32(i) => display_float(*i, f),
NumberValue::Float64(i) => display_float(*i, f),
NumberValue::Decimal64(v, s) => {
write!(f, "{}", display_decimal_128(*v as i128, s.scale))
}
Expand Down Expand Up @@ -143,11 +143,13 @@ impl Value {
}
Value::Vector(vals) => {
write!(f, "[")?;
let mut buffer = zmij::Buffer::new();
for (i, val) in vals.iter().enumerate() {
if i > 0 {
write!(f, ",")?;
}
write!(f, "{val}")?;
let s = buffer.format_finite(*val);
write!(f, "{s}")?;
}
write!(f, "]")?;
Ok(())
Expand All @@ -156,6 +158,58 @@ impl Value {
}
}

trait FloatForDisplay: Copy {
fn is_nan(self) -> bool;
fn is_infinite(self) -> bool;
fn is_sign_negative(self) -> bool;
fn write_with(self, buf: &mut zmij::Buffer) -> &str;
}

impl FloatForDisplay for f32 {
fn is_nan(self) -> bool {
f32::is_nan(self)
}
fn is_infinite(self) -> bool {
f32::is_infinite(self)
}
fn is_sign_negative(self) -> bool {
f32::is_sign_negative(self)
}
fn write_with(self, buf: &mut zmij::Buffer) -> &str {
buf.format_finite(self)
}
}

impl FloatForDisplay for f64 {
fn is_nan(self) -> bool {
f64::is_nan(self)
}
fn is_infinite(self) -> bool {
f64::is_infinite(self)
}
fn is_sign_negative(self) -> bool {
f64::is_sign_negative(self)
}
fn write_with(self, buf: &mut zmij::Buffer) -> &str {
buf.format_finite(self)
}
}

fn display_float<T: FloatForDisplay>(num: T, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if num.is_nan() {
write!(f, "NaN")
} else if num.is_infinite() {
if num.is_sign_negative() {
write!(f, "-inf")
} else {
write!(f, "inf")
}
} else {
let mut buffer = zmij::Buffer::new();
write!(f, "{}", num.write_with(&mut buffer))
}
}

pub fn display_decimal_128(num: i128, scale: u8) -> String {
let mut buf = String::new();
if scale == 0 {
Expand Down
Loading