databend_driver_core/value/format/
display.rs

1// Copyright 2021 Datafuse Labs
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use crate::_macro_internal::Value;
16use crate::value::base::{DAYS_FROM_CE, TIMESTAMP_FORMAT, TIMESTAMP_TIMEZONE_FORMAT};
17use crate::value::NumberValue;
18use chrono::NaiveDate;
19use ethnum::i256;
20use std::fmt::Write;
21
22impl std::fmt::Display for Value {
23    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
24        self.display_value(f, true)
25    }
26}
27
28impl std::fmt::Display for NumberValue {
29    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
30        match self {
31            NumberValue::Int8(i) => write!(f, "{i}"),
32            NumberValue::Int16(i) => write!(f, "{i}"),
33            NumberValue::Int32(i) => write!(f, "{i}"),
34            NumberValue::Int64(i) => write!(f, "{i}"),
35            NumberValue::UInt8(i) => write!(f, "{i}"),
36            NumberValue::UInt16(i) => write!(f, "{i}"),
37            NumberValue::UInt32(i) => write!(f, "{i}"),
38            NumberValue::UInt64(i) => write!(f, "{i}"),
39            NumberValue::Float32(i) => write!(f, "{i}"),
40            NumberValue::Float64(i) => write!(f, "{i}"),
41            NumberValue::Decimal128(v, s) => write!(f, "{}", display_decimal_128(*v, s.scale)),
42            NumberValue::Decimal256(v, s) => write!(f, "{}", display_decimal_256(*v, s.scale)),
43        }
44    }
45}
46
47impl Value {
48    // Used as output of cli
49    // Compatible with Databend, strings inside nested types are quoted.
50    pub fn display_value(&self, f: &mut std::fmt::Formatter<'_>, raw: bool) -> std::fmt::Result {
51        match self {
52            Value::Null => write!(f, "NULL"),
53            Value::EmptyArray => write!(f, "[]"),
54            Value::EmptyMap => write!(f, "{{}}"),
55            Value::Boolean(b) => {
56                if *b {
57                    write!(f, "true")
58                } else {
59                    write!(f, "false")
60                }
61            }
62            Value::Number(n) => write!(f, "{n}"),
63            Value::Binary(s) => write!(f, "{}", hex::encode_upper(s)),
64            Value::String(s)
65            | Value::Bitmap(s)
66            | Value::Variant(s)
67            | Value::Interval(s)
68            | Value::Geometry(s)
69            | Value::Geography(s) => {
70                if raw {
71                    write!(f, "{s}")
72                } else {
73                    write!(f, "'{s}'")
74                }
75            }
76            Value::Timestamp(dt) => {
77                let formatted = dt.strftime(TIMESTAMP_FORMAT);
78                if raw {
79                    write!(f, "{formatted}")
80                } else {
81                    write!(f, "'{formatted}'")
82                }
83            }
84            Value::TimestampTz(dt) => {
85                let formatted = dt.strftime(TIMESTAMP_TIMEZONE_FORMAT);
86                if raw {
87                    write!(f, "{formatted}")
88                } else {
89                    write!(f, "'{formatted}'")
90                }
91            }
92            Value::Date(i) => {
93                let days = i + DAYS_FROM_CE;
94                let d = NaiveDate::from_num_days_from_ce_opt(days).unwrap_or_default();
95                if raw {
96                    write!(f, "{d}")
97                } else {
98                    write!(f, "'{d}'")
99                }
100            }
101            Value::Array(vals) => {
102                write!(f, "[")?;
103                for (i, val) in vals.iter().enumerate() {
104                    if i > 0 {
105                        write!(f, ",")?;
106                    }
107                    val.display_value(f, false)?;
108                }
109                write!(f, "]")?;
110                Ok(())
111            }
112            Value::Map(kvs) => {
113                write!(f, "{{")?;
114                for (i, (key, val)) in kvs.iter().enumerate() {
115                    if i > 0 {
116                        write!(f, ",")?;
117                    }
118                    key.display_value(f, false)?;
119                    write!(f, ":")?;
120                    val.display_value(f, false)?;
121                }
122                write!(f, "}}")?;
123                Ok(())
124            }
125            Value::Tuple(vals) => {
126                write!(f, "(")?;
127                for (i, val) in vals.iter().enumerate() {
128                    if i > 0 {
129                        write!(f, ",")?;
130                    }
131                    val.display_value(f, false)?;
132                }
133                write!(f, ")")?;
134                Ok(())
135            }
136            Value::Vector(vals) => {
137                write!(f, "[")?;
138                for (i, val) in vals.iter().enumerate() {
139                    if i > 0 {
140                        write!(f, ",")?;
141                    }
142                    write!(f, "{val}")?;
143                }
144                write!(f, "]")?;
145                Ok(())
146            }
147        }
148    }
149}
150
151pub fn display_decimal_128(num: i128, scale: u8) -> String {
152    let mut buf = String::new();
153    if scale == 0 {
154        write!(buf, "{num}").unwrap();
155    } else {
156        let pow_scale = 10_i128.pow(scale as u32);
157        if num >= 0 {
158            write!(
159                buf,
160                "{}.{:0>width$}",
161                num / pow_scale,
162                (num % pow_scale).abs(),
163                width = scale as usize
164            )
165            .unwrap();
166        } else {
167            write!(
168                buf,
169                "-{}.{:0>width$}",
170                -num / pow_scale,
171                (num % pow_scale).abs(),
172                width = scale as usize
173            )
174            .unwrap();
175        }
176    }
177    buf
178}
179
180pub fn display_decimal_256(num: i256, scale: u8) -> String {
181    let mut buf = String::new();
182    if scale == 0 {
183        write!(buf, "{}", num).unwrap();
184    } else {
185        let pow_scale = i256::from(10).pow(scale as u32);
186        // -1/10 = 0
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            )
195        } else {
196            write!(
197                buf,
198                "-{}.{:0>width$}",
199                -num / pow_scale,
200                (num % pow_scale).wrapping_abs(),
201                width = scale as usize
202            )
203        }
204        .expect("display_decimal_256 should not fail");
205    }
206    String::from_utf8_lossy(buf.as_bytes()).to_string()
207}