models_parser/ast/
data_type.rs

1// Licensed under the Apache License, Version 2.0 (the "License");
2// you may not use this file except in compliance with the License.
3// You may obtain a copy of the License at
4//
5// http://www.apache.org/licenses/LICENSE-2.0
6//
7// Unless required by applicable law or agreed to in writing, software
8// distributed under the License is distributed on an "AS IS" BASIS,
9// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10// See the License for the specific language governing permissions and
11// limitations under the License.
12
13#[cfg(not(feature = "std"))]
14use alloc::boxed::Box;
15use core::fmt;
16
17#[cfg(feature = "serde")]
18use serde::{Deserialize, Serialize};
19
20use crate::ast::ObjectName;
21
22/// SQL data types
23#[derive(Debug, Clone, PartialEq, Eq, Hash)]
24#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
25pub enum DataType {
26    /// Fixed-length character type e.g. CHAR(10)
27    Char(Option<u64>),
28    /// Variable-length character type e.g. VARCHAR(10)
29    Varchar(Option<u64>),
30    /// Uuid type
31    Uuid,
32    /// Large character object e.g. CLOB(1000)
33    Clob(u64),
34    /// Fixed-length binary type e.g. BINARY(10)
35    Binary(u64),
36    /// Variable-length binary type e.g. VARBINARY(10)
37    Varbinary(Option<u64>),
38    /// Large binary object e.g. BLOB(1000)
39    Blob(Option<u64>),
40    /// Decimal type with optional precision and scale e.g. DECIMAL(10,2)
41    Decimal(Option<u64>, Option<u64>),
42    /// Floating point with optional precision e.g. FLOAT(8)
43    Float(Option<u64>),
44    /// Tiny integer with optional display width e.g. TINYINT or TINYINT(3)
45    TinyInt(Option<u64>),
46    /// Small integer with optional display width e.g. SMALLINT or SMALLINT(5)
47    SmallInt(Option<u64>),
48    /// INT with optional display width e.g. INT or INT(11)
49    Int(Option<u64>),
50    /// Big integer with optional display width e.g. BIGINT or BIGINT(20)
51    BigInt(Option<u64>),
52    /// Floating point e.g. REAL
53    Real,
54    /// Double e.g. DOUBLE PRECISION
55    Double,
56    /// Boolean
57    Boolean,
58    /// Date
59    Date,
60    /// Time
61    Time,
62    /// Timestamp
63    Timestamp,
64    /// Interval
65    Interval,
66    /// Regclass used in postgresql serial
67    Regclass,
68    /// Text
69    Text,
70    /// String
71    String,
72    /// Bytea
73    Bytea,
74    /// Custom type such as enums
75    Custom(ObjectName),
76    /// Arrays
77    Array(Box<DataType>),
78    /// JSON
79    Json,
80    /// Serial PostgeSQL type
81    Serial,
82}
83
84impl fmt::Display for DataType {
85    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
86        match self {
87            DataType::Serial => write!(f, "SERIAL"),
88            DataType::Json => write!(f, "JSON"),
89            DataType::Char(size) => format_type_with_optional_length(f, "CHAR", size),
90            DataType::Varchar(size) => format_type_with_optional_length(f, "VARCHAR", size),
91            DataType::Uuid => write!(f, "UUID"),
92            DataType::Clob(size) => write!(f, "CLOB({})", size),
93            DataType::Binary(size) => write!(f, "BINARY({})", size),
94            DataType::Varbinary(size) => format_type_with_optional_length(f, "VARBINARY", size),
95            DataType::Blob(size) => {
96                if let Some(size) = size {
97                    write!(f, "BLOB({})", size)
98                } else {
99                    write!(f, "BLOB")
100                }
101            }
102            DataType::Decimal(precision, scale) => {
103                if let Some(scale) = scale {
104                    write!(f, "NUMERIC({},{})", precision.unwrap(), scale)
105                } else {
106                    format_type_with_optional_length(f, "NUMERIC", precision)
107                }
108            }
109            DataType::Float(size) => format_type_with_optional_length(f, "FLOAT", size),
110            DataType::TinyInt(zerofill) => format_type_with_optional_length(f, "TINYINT", zerofill),
111            DataType::SmallInt(zerofill) => {
112                format_type_with_optional_length(f, "SMALLINT", zerofill)
113            }
114            DataType::Int(zerofill) => {
115                if let Some(len) = zerofill {
116                    write!(f, "INT({})", len)
117                } else {
118                    write!(f, "INTEGER")
119                }
120            }
121            DataType::BigInt(zerofill) => format_type_with_optional_length(f, "BIGINT", zerofill),
122            DataType::Real => write!(f, "REAL"),
123            DataType::Double => write!(f, "DOUBLE PRECISION"),
124            DataType::Boolean => write!(f, "BOOLEAN"),
125            DataType::Date => write!(f, "DATE"),
126            DataType::Time => write!(f, "TIME"),
127            DataType::Timestamp => write!(f, "TIMESTAMP"),
128            DataType::Interval => write!(f, "INTERVAL"),
129            DataType::Regclass => write!(f, "REGCLASS"),
130            DataType::Text => write!(f, "TEXT"),
131            DataType::String => write!(f, "STRING"),
132            DataType::Bytea => write!(f, "BYTEA"),
133            DataType::Array(ty) => write!(f, "{}[]", ty),
134            DataType::Custom(ty) => write!(f, "{}", ty),
135        }
136    }
137}
138impl DataType {
139    pub fn custom(custom: &str) -> Self {
140        Self::Custom(ObjectName(vec![super::Ident::new(custom)]))
141    }
142}
143
144fn format_type_with_optional_length(
145    f: &mut fmt::Formatter,
146    sql_type: &'static str,
147    len: &Option<u64>,
148) -> fmt::Result {
149    write!(f, "{}", sql_type)?;
150    if let Some(len) = len {
151        write!(f, "({})", len)?;
152    }
153    Ok(())
154}