1use candid::CandidType;
2use serde::{Deserialize, Serialize};
3
4use crate::dbms::types::DataTypeKind;
5
6#[derive(Clone, Copy, Debug, PartialEq, Eq)]
8pub struct ColumnDef {
9 pub name: &'static str,
11 pub data_type: DataTypeKind,
13 pub nullable: bool,
15 pub primary_key: bool,
17 pub foreign_key: Option<ForeignKeyDef>,
19}
20
21#[derive(Clone, Copy, Debug, PartialEq, Eq)]
23pub struct ForeignKeyDef {
24 pub local_column: &'static str,
26 pub foreign_table: &'static str,
28 pub foreign_column: &'static str,
30}
31
32#[derive(Clone, Debug, PartialEq, Eq, CandidType, Serialize, Deserialize)]
37pub struct CandidColumnDef {
38 pub table: Option<String>,
40 pub name: String,
42 pub data_type: DataTypeKind,
44 pub nullable: bool,
46 pub primary_key: bool,
48 pub foreign_key: Option<CandidForeignKeyDef>,
50}
51
52#[derive(Clone, Debug, PartialEq, Eq, CandidType, Serialize, Deserialize)]
57pub struct CandidForeignKeyDef {
58 pub local_column: String,
60 pub foreign_table: String,
62 pub foreign_column: String,
64}
65
66impl From<ColumnDef> for CandidColumnDef {
67 fn from(def: ColumnDef) -> Self {
68 Self {
69 table: None,
70 name: def.name.to_string(),
71 data_type: def.data_type,
72 nullable: def.nullable,
73 primary_key: def.primary_key,
74 foreign_key: def.foreign_key.map(CandidForeignKeyDef::from),
75 }
76 }
77}
78
79impl From<ForeignKeyDef> for CandidForeignKeyDef {
80 fn from(def: ForeignKeyDef) -> Self {
81 Self {
82 local_column: def.local_column.to_string(),
83 foreign_table: def.foreign_table.to_string(),
84 foreign_column: def.foreign_column.to_string(),
85 }
86 }
87}
88
89#[cfg(test)]
90mod test {
91
92 use super::*;
93 use crate::dbms::types::DataTypeKind;
94
95 #[test]
96 fn test_should_create_column_def() {
97 let column = ColumnDef {
98 name: "id",
99 data_type: DataTypeKind::Uint32,
100 nullable: false,
101 primary_key: true,
102 foreign_key: None,
103 };
104
105 assert_eq!(column.name, "id");
106 assert_eq!(column.data_type, DataTypeKind::Uint32);
107 assert!(!column.nullable);
108 assert!(column.primary_key);
109 assert!(column.foreign_key.is_none());
110 }
111
112 #[test]
113 fn test_should_create_column_def_with_foreign_key() {
114 let fk = ForeignKeyDef {
115 local_column: "user_id",
116 foreign_table: "users",
117 foreign_column: "id",
118 };
119
120 let column = ColumnDef {
121 name: "user_id",
122 data_type: DataTypeKind::Uint32,
123 nullable: false,
124 primary_key: false,
125 foreign_key: Some(fk),
126 };
127
128 assert_eq!(column.name, "user_id");
129 assert!(column.foreign_key.is_some());
130 let fk_def = column.foreign_key.unwrap();
131 assert_eq!(fk_def.local_column, "user_id");
132 assert_eq!(fk_def.foreign_table, "users");
133 assert_eq!(fk_def.foreign_column, "id");
134 }
135
136 #[test]
137 #[allow(clippy::clone_on_copy)]
138 fn test_should_clone_column_def() {
139 let column = ColumnDef {
140 name: "email",
141 data_type: DataTypeKind::Text,
142 nullable: true,
143 primary_key: false,
144 foreign_key: None,
145 };
146
147 let cloned = column.clone();
148 assert_eq!(column, cloned);
149 }
150
151 #[test]
152 fn test_should_compare_column_defs() {
153 let column1 = ColumnDef {
154 name: "id",
155 data_type: DataTypeKind::Uint32,
156 nullable: false,
157 primary_key: true,
158 foreign_key: None,
159 };
160
161 let column2 = ColumnDef {
162 name: "id",
163 data_type: DataTypeKind::Uint32,
164 nullable: false,
165 primary_key: true,
166 foreign_key: None,
167 };
168
169 let column3 = ColumnDef {
170 name: "name",
171 data_type: DataTypeKind::Text,
172 nullable: true,
173 primary_key: false,
174 foreign_key: None,
175 };
176
177 assert_eq!(column1, column2);
178 assert_ne!(column1, column3);
179 }
180
181 #[test]
182 fn test_should_create_foreign_key_def() {
183 let fk = ForeignKeyDef {
184 local_column: "post_id",
185 foreign_table: "posts",
186 foreign_column: "id",
187 };
188
189 assert_eq!(fk.local_column, "post_id");
190 assert_eq!(fk.foreign_table, "posts");
191 assert_eq!(fk.foreign_column, "id");
192 }
193
194 #[test]
195 #[allow(clippy::clone_on_copy)]
196 fn test_should_clone_foreign_key_def() {
197 let fk = ForeignKeyDef {
198 local_column: "author_id",
199 foreign_table: "authors",
200 foreign_column: "id",
201 };
202
203 let cloned = fk.clone();
204 assert_eq!(fk, cloned);
205 }
206
207 #[test]
208 fn test_should_compare_foreign_key_defs() {
209 let fk1 = ForeignKeyDef {
210 local_column: "user_id",
211 foreign_table: "users",
212 foreign_column: "id",
213 };
214
215 let fk2 = ForeignKeyDef {
216 local_column: "user_id",
217 foreign_table: "users",
218 foreign_column: "id",
219 };
220
221 let fk3 = ForeignKeyDef {
222 local_column: "category_id",
223 foreign_table: "categories",
224 foreign_column: "id",
225 };
226
227 assert_eq!(fk1, fk2);
228 assert_ne!(fk1, fk3);
229 }
230
231 #[test]
232 fn test_should_create_candid_column_def_with_table() {
233 let col = CandidColumnDef {
234 table: Some("users".to_string()),
235 name: "id".to_string(),
236 data_type: DataTypeKind::Uint32,
237 nullable: false,
238 primary_key: true,
239 foreign_key: None,
240 };
241 assert_eq!(col.table, Some("users".to_string()));
242 }
243
244 #[test]
245 fn test_should_convert_column_def_to_candid_with_none_table() {
246 let col = ColumnDef {
247 name: "id",
248 data_type: DataTypeKind::Uint32,
249 nullable: false,
250 primary_key: true,
251 foreign_key: None,
252 };
253 let candid_col = CandidColumnDef::from(col);
254 assert_eq!(candid_col.table, None);
255 assert_eq!(candid_col.name, "id");
256 }
257}