1pub trait FieldType {
2 fn get_type_str(&self) -> String;
3}
4
5pub trait Field {
6 fn get_name(&self) -> String;
7 fn get_type(&self) -> Box<dyn FieldType>;
8 fn get_default(&self) -> Option<String> {
9 None
10 }
11 fn get_nullable(&self) -> bool {
12 true
13 }
14 fn get_primary_key(&self) -> bool {
15 false
16 }
17 fn get_unique(&self) -> bool {
18 false
19 }
20 fn get_auto_increment(&self) -> bool {
21 false
22 }
23 fn get_comment(&self) -> Option<String> {
24 None
25 }
26 fn get_create_sql(&self) -> String {
27 let mut sql = format!("`{}` {}", self.get_name(), self.get_type().get_type_str());
28 if let Some(default) = self.get_default() {
29 sql.push_str(&format!(" DEFAULT {}", default));
30 }
31 if !self.get_nullable() {
32 sql.push_str(" NOT NULL");
33 }
34 if self.get_primary_key() {
35 sql.push_str(" PRIMARY KEY");
36 }
37 if self.get_unique() {
38 sql.push_str(" UNIQUE");
39 }
40 if self.get_auto_increment() {
41 sql.push_str(" AUTO_INCREMENT");
42 }
43 if let Some(comment) = self.get_comment() {
44 sql.push_str(&format!(" COMMENT '{}'", comment));
45 }
46 sql
47 }
48}
49
50#[cfg(test)]
51mod tests {
52 use super::*;
53 use serde::{Deserialize, Serialize};
54
55 #[derive(Debug, Serialize, Deserialize, Eq, PartialEq)]
56 struct TestIntField {
57 name: String,
58 default: Option<String>,
59 nullable: bool,
60 primary_key: bool,
61 unique: bool,
62 auto_increment: bool,
63 comment: Option<String>,
64 }
65
66 impl Field for TestIntField {
67 fn get_name(&self) -> String {
68 self.name.clone()
69 }
70 fn get_type(&self) -> Box<dyn FieldType> {
71 Box::new(IntType)
72 }
73 fn get_default(&self) -> Option<String> {
74 self.default.clone()
75 }
76 fn get_nullable(&self) -> bool {
77 self.nullable
78 }
79 fn get_primary_key(&self) -> bool {
80 self.primary_key
81 }
82 fn get_unique(&self) -> bool {
83 self.unique
84 }
85 fn get_auto_increment(&self) -> bool {
86 self.auto_increment
87 }
88 fn get_comment(&self) -> Option<String> {
89 self.comment.clone()
90 }
91 }
92
93 struct IntType;
94
95 impl FieldType for IntType {
96 fn get_type_str(&self) -> String {
97 "INT".to_string()
98 }
99 }
100
101 #[test]
102 fn test_int_field() {
103 let field = TestIntField {
104 name: "id".to_string(),
105 default: None,
106 nullable: false,
107 primary_key: true,
108 unique: true,
109 auto_increment: true,
110 comment: Some("ID".to_string()),
111 };
112 assert_eq!(field.get_name(), "id");
113 assert_eq!(field.get_type().get_type_str(), "INT");
114 assert_eq!(
115 field.get_create_sql(),
116 "`id` INT NOT NULL PRIMARY KEY UNIQUE AUTO_INCREMENT COMMENT 'ID'"
117 );
118 }
119}