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::Decimal64(v, s) => {
42                write!(f, "{}", display_decimal_128(*v as i128, s.scale))
43            }
44            NumberValue::Decimal128(v, s) => write!(f, "{}", display_decimal_128(*v, s.scale)),
45            NumberValue::Decimal256(v, s) => write!(f, "{}", display_decimal_256(*v, s.scale)),
46        }
47    }
48}
49
50impl Value {
51    // Used as output of cli
52    // Compatible with Databend, strings inside nested types are quoted.
53    pub fn display_value(&self, f: &mut std::fmt::Formatter<'_>, raw: bool) -> std::fmt::Result {
54        match self {
55            Value::Null => write!(f, "NULL"),
56            Value::EmptyArray => write!(f, "[]"),
57            Value::EmptyMap => write!(f, "{{}}"),
58            Value::Boolean(b) => {
59                if *b {
60                    write!(f, "true")
61                } else {
62                    write!(f, "false")
63                }
64            }
65            Value::Number(n) => write!(f, "{n}"),
66            Value::Binary(s) => write!(f, "{}", hex::encode_upper(s)),
67            Value::String(s)
68            | Value::Bitmap(s)
69            | Value::Variant(s)
70            | Value::Interval(s)
71            | Value::Geometry(s)
72            | Value::Geography(s) => {
73                if raw {
74                    write!(f, "{s}")
75                } else {
76                    write!(f, "'{s}'")
77                }
78            }
79            Value::Timestamp(dt) => {
80                let formatted = dt.strftime(TIMESTAMP_FORMAT);
81                if raw {
82                    write!(f, "{formatted}")
83                } else {
84                    write!(f, "'{formatted}'")
85                }
86            }
87            Value::TimestampTz(dt) => {
88                let formatted = dt.strftime(TIMESTAMP_TIMEZONE_FORMAT);
89                if raw {
90                    write!(f, "{formatted}")
91                } else {
92                    write!(f, "'{formatted}'")
93                }
94            }
95            Value::Date(i) => {
96                let days = i + DAYS_FROM_CE;
97                let d = NaiveDate::from_num_days_from_ce_opt(days).unwrap_or_default();
98                if raw {
99                    write!(f, "{d}")
100                } else {
101                    write!(f, "'{d}'")
102                }
103            }
104            Value::Array(vals) => {
105                write!(f, "[")?;
106                for (i, val) in vals.iter().enumerate() {
107                    if i > 0 {
108                        write!(f, ",")?;
109                    }
110                    val.display_value(f, false)?;
111                }
112                write!(f, "]")?;
113                Ok(())
114            }
115            Value::Map(kvs) => {
116                write!(f, "{{")?;
117                for (i, (key, val)) in kvs.iter().enumerate() {
118                    if i > 0 {
119                        write!(f, ",")?;
120                    }
121                    key.display_value(f, false)?;
122                    write!(f, ":")?;
123                    val.display_value(f, false)?;
124                }
125                write!(f, "}}")?;
126                Ok(())
127            }
128            Value::Tuple(vals) => {
129                write!(f, "(")?;
130                for (i, val) in vals.iter().enumerate() {
131                    if i > 0 {
132                        write!(f, ",")?;
133                    }
134                    val.display_value(f, false)?;
135                }
136                write!(f, ")")?;
137                Ok(())
138            }
139            Value::Vector(vals) => {
140                write!(f, "[")?;
141                for (i, val) in vals.iter().enumerate() {
142                    if i > 0 {
143                        write!(f, ",")?;
144                    }
145                    write!(f, "{val}")?;
146                }
147                write!(f, "]")?;
148                Ok(())
149            }
150        }
151    }
152}
153
154pub fn display_decimal_128(num: i128, scale: u8) -> String {
155    let mut buf = String::new();
156    if scale == 0 {
157        write!(buf, "{num}").unwrap();
158    } else {
159        let pow_scale = 10_i128.pow(scale as u32);
160        if num >= 0 {
161            write!(
162                buf,
163                "{}.{:0>width$}",
164                num / pow_scale,
165                (num % pow_scale).abs(),
166                width = scale as usize
167            )
168            .unwrap();
169        } else {
170            write!(
171                buf,
172                "-{}.{:0>width$}",
173                -num / pow_scale,
174                (num % pow_scale).abs(),
175                width = scale as usize
176            )
177            .unwrap();
178        }
179    }
180    buf
181}
182
183pub fn display_decimal_256(num: i256, scale: u8) -> String {
184    let mut buf = String::new();
185    if scale == 0 {
186        write!(buf, "{}", num).unwrap();
187    } else {
188        let pow_scale = i256::from(10).pow(scale as u32);
189        // -1/10 = 0
190        if !num.is_negative() {
191            write!(
192                buf,
193                "{}.{:0>width$}",
194                num / pow_scale,
195                (num % pow_scale).wrapping_abs(),
196                width = scale as usize
197            )
198        } else {
199            write!(
200                buf,
201                "-{}.{:0>width$}",
202                -num / pow_scale,
203                (num % pow_scale).wrapping_abs(),
204                width = scale as usize
205            )
206        }
207        .expect("display_decimal_256 should not fail");
208    }
209    String::from_utf8_lossy(buf.as_bytes()).to_string()
210}