1#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
2pub enum ColumnType {
3 Sequence,
4 LongSequence,
5 Byte,
6 Short,
7 Int,
8 Long,
9 Float,
10 Double,
11 Decimal,
12 Boolean,
13 Date,
14 DateTime,
15 Time,
16 Timestamp,
17 TimestampTz,
18 Char,
19 Varchar,
20 Enum,
21 Text,
22 CiText,
23 CsText,
24 Binary,
25 Uuid,
26 Json,
27 Array,
28}
29impl ColumnType {
30 pub const VARIANTS: [ColumnType; 25] = [
31 ColumnType::Sequence,
32 ColumnType::LongSequence,
33 ColumnType::Byte,
34 ColumnType::Short,
35 ColumnType::Int,
36 ColumnType::Long,
37 ColumnType::Float,
38 ColumnType::Double,
39 ColumnType::Decimal,
40 ColumnType::Boolean,
41 ColumnType::Date,
42 ColumnType::DateTime,
43 ColumnType::Time,
44 ColumnType::Timestamp,
45 ColumnType::TimestampTz,
46 ColumnType::Char,
47 ColumnType::Varchar,
48 ColumnType::Enum,
49 ColumnType::Text,
50 ColumnType::CiText,
51 ColumnType::CsText,
52 ColumnType::Binary,
53 ColumnType::Uuid,
54 ColumnType::Json,
55 ColumnType::Array,
56 ];
57
58 pub fn name(&self) -> &'static str {
59 match self {
60 ColumnType::Sequence => "SEQUENCE",
61 ColumnType::LongSequence => "LONGSEQUENCE",
62 ColumnType::Byte => "BYTE",
63 ColumnType::Short => "SHORT",
64 ColumnType::Int => "INT",
65 ColumnType::Long => "LONG",
66 ColumnType::Float => "FLOAT",
67 ColumnType::Double => "DOUBLE",
68 ColumnType::Decimal => "DECIMAL",
69 ColumnType::Boolean => "BOOLEAN",
70 ColumnType::Date => "DATE",
71 ColumnType::DateTime => "DATETIME",
72 ColumnType::Time => "TIME",
73 ColumnType::Timestamp => "TIMESTAMP",
74 ColumnType::TimestampTz => "TIMESTAMPTZ",
75 ColumnType::Char => "CHAR",
76 ColumnType::Varchar => "VARCHAR",
77 ColumnType::Enum => "ENUM",
78 ColumnType::Text => "TEXT",
79 ColumnType::CiText => "CITEXT",
80 ColumnType::CsText => "CSTEXT",
81 ColumnType::Binary => "BINARY",
82 ColumnType::Uuid => "UUID",
83 ColumnType::Json => "JSON",
84 ColumnType::Array => "ARRAY",
85 }
86 }
87
88 pub fn is_text(&self) -> bool {
89 matches!(
90 self,
91 ColumnType::Char
92 | ColumnType::Varchar
93 | ColumnType::Enum
94 | ColumnType::Text
95 | ColumnType::CiText
96 | ColumnType::CsText
97 | ColumnType::Json
98 | ColumnType::Uuid
99 )
100 }
101
102 pub fn is_numeric(&self) -> bool {
103 matches!(
104 self,
105 ColumnType::Sequence
106 | ColumnType::LongSequence
107 | ColumnType::Byte
108 | ColumnType::Short
109 | ColumnType::Int
110 | ColumnType::Long
111 | ColumnType::Float
112 | ColumnType::Double
113 | ColumnType::Decimal
114 )
115 }
116
117 pub fn from_type_name(type_name: &str) -> Result<Self, String> {
118 let upper = type_name.trim().to_uppercase();
119 Self::VARIANTS
120 .iter()
121 .copied()
122 .find(|v| v.name() == upper)
123 .ok_or_else(|| format!("The type '{}' is not valid.", type_name))
124 }
125}
126
127#[cfg(test)]
128mod tests {
129 use super::*;
130
131 #[test]
132 fn name_roundtrip_and_from_type_name() {
133 for v in ColumnType::VARIANTS.iter() {
134 let name = v.name();
135 let parsed = ColumnType::from_type_name(name).expect("must parse");
136 assert_eq!(*v, parsed);
137 }
138 assert_eq!(
140 ColumnType::from_type_name(" int ").unwrap(),
141 ColumnType::Int
142 );
143 let err = ColumnType::from_type_name("notatype").unwrap_err();
145 assert!(err.contains("notatype"));
146 }
147
148 #[test]
149 fn is_text_and_numeric_classification() {
150 assert!(ColumnType::Varchar.is_text());
151 assert!(ColumnType::Text.is_text());
152 assert!(!ColumnType::Int.is_text());
153
154 assert!(ColumnType::Int.is_numeric());
155 assert!(ColumnType::Decimal.is_numeric());
156 assert!(!ColumnType::Varchar.is_numeric());
157 }
158}