Skip to main content

schema_model/model/
column_type.rs

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        // Lower/space handling
139        assert_eq!(
140            ColumnType::from_type_name(" int ").unwrap(),
141            ColumnType::Int
142        );
143        // Error case
144        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}