Skip to main content

schema_model/model/
column.rs

1use crate::model::column_type::ColumnType;
2use crate::model::types::BooleanMode;
3
4#[derive(Debug, Clone)]
5pub struct Column {
6    schema_name: Option<String>,
7    name: String,
8    column_type: ColumnType,
9    length: i32,
10    scale: i32,
11    required: bool,
12    check_constraint: Option<String>,
13    default_constraint: Option<String>,
14    generated: Option<String>,
15    min_value: Option<f64>,
16    max_value: Option<f64>,
17    enum_type: Option<String>,
18    element_type: Option<String>,
19}
20
21impl Column {
22    pub fn new<S: Into<String>>(
23        schema_name: Option<S>,
24        name: S,
25        column_type: ColumnType,
26        length: i32,
27        scale: i32,
28        required: bool,
29    ) -> Self {
30        Self {
31            schema_name: schema_name.map(|s| s.into()),
32            name: name.into(),
33            column_type,
34            length,
35            scale,
36            required,
37            check_constraint: None,
38            default_constraint: None,
39            generated: None,
40            min_value: None,
41            max_value: None,
42            enum_type: None,
43            element_type: None,
44        }
45    }
46
47    pub fn new_all<S: Into<String>>(
48        schema_name: Option<S>,
49        name: S,
50        column_type: ColumnType,
51        length: i32,
52        scale: i32,
53        required: bool,
54        check_constraint: Option<String>,
55        default_constraint: Option<String>,
56        generated: Option<String>,
57        min_value: Option<f64>,
58        max_value: Option<f64>,
59        enum_type: Option<String>,
60        element_type: Option<String>,
61    ) -> Self {
62        Self {
63            schema_name: schema_name.map(|s| s.into()),
64            name: name.into(),
65            column_type,
66            length,
67            scale,
68            required,
69            check_constraint,
70            default_constraint,
71            generated,
72            min_value,
73            max_value,
74            enum_type,
75            element_type,
76        }
77    }
78
79    pub fn schema_name(&self) -> Option<&str> {
80        self.schema_name.as_deref()
81    }
82
83    pub fn name(&self) -> &str {
84        &self.name
85    }
86
87    pub fn column_type(&self) -> ColumnType {
88        self.column_type
89    }
90
91    pub fn length(&self) -> i32 {
92        self.length
93    }
94
95    pub fn scale(&self) -> i32 {
96        self.scale
97    }
98
99    pub fn required(&self) -> bool {
100        self.required
101    }
102
103    // Compatibility alias: elsewhere in the codebase `is_required()` is used.
104    pub fn is_required(&self) -> bool {
105        self.required
106    }
107
108    pub fn check_constraint(&self) -> Option<&str> {
109        self.check_constraint.as_deref()
110    }
111
112    pub fn default_constraint(&self) -> Option<&str> {
113        self.default_constraint.as_deref()
114    }
115
116    pub fn generated(&self) -> Option<&str> {
117        self.generated.as_deref()
118    }
119
120    pub fn min_value(&self) -> Option<f64> {
121        self.min_value
122    }
123
124    pub fn max_value(&self) -> Option<f64> {
125        self.max_value
126    }
127
128    pub fn enum_type(&self) -> Option<&str> {
129        self.enum_type.as_deref()
130    }
131
132    pub fn element_type(&self) -> Option<&str> {
133        self.element_type.as_deref()
134    }
135
136    pub fn has_min_or_max_value(&self) -> bool {
137        self.min_value.is_some() || self.max_value.is_some()
138    }
139
140    pub fn needs_check_constraints(&self, boolean_mode: BooleanMode) -> bool {
141        self.check_constraint.is_some()
142            || self.min_value.is_some()
143            || self.max_value.is_some()
144            || self.enum_type.is_some()
145            || (self.column_type == ColumnType::Boolean && boolean_mode != BooleanMode::Native)
146    }
147}
148
149#[cfg(test)]
150mod tests {
151    use super::*;
152    use crate::model::types::BooleanMode;
153
154    #[test]
155    fn constructor_and_getters() {
156        let c = Column::new(None, "name", ColumnType::Varchar, 255, 0, true);
157        assert_eq!(c.name(), "name");
158        assert_eq!(c.column_type(), ColumnType::Varchar);
159        assert_eq!(c.length(), 255);
160        assert_eq!(c.scale(), 0);
161        assert!(c.required());
162        assert!(c.is_required());
163    }
164
165    #[test]
166    fn needs_check_constraints_logic() {
167        let c = Column::new(None, "b", ColumnType::Boolean, 0, 0, false);
168        // boolean with non-native boolean mode => needs constraints
169        assert!(c.needs_check_constraints(BooleanMode::YesNo));
170        // boolean with native => no unless other attributes set
171        assert!(!c.needs_check_constraints(BooleanMode::Native));
172    }
173
174    #[test]
175    fn has_min_or_max_value() {
176        let c = Column::new(None, "n", ColumnType::Int, 0, 0, false);
177        assert!(!c.has_min_or_max_value());
178    }
179}