1use crate::{
12 expr::SimpleExpr,
13 types::{DynIden, IntoIden, TableRef},
14};
15
16#[derive(Debug, Clone, PartialEq, Eq)]
21#[non_exhaustive]
22pub enum ColumnType {
23 Char(Option<u32>),
25 String(Option<u32>),
27 Text,
29 TinyInteger,
31 SmallInteger,
33 Integer,
35 BigInteger,
37 Float,
39 Double,
41 Decimal(Option<(u32, u32)>),
43 Boolean,
45 Date,
47 Time,
49 DateTime,
51 Timestamp,
53 TimestampWithTimeZone,
55 Binary(Option<u32>),
57 VarBinary(u32),
59 Blob,
61 Uuid,
63 Json,
65 JsonBinary,
67 Array(Box<ColumnType>),
69 Custom(String),
75}
76
77#[derive(Debug, Clone)]
99pub struct ColumnDef {
100 pub(crate) name: DynIden,
101 pub(crate) column_type: Option<ColumnType>,
102 pub(crate) not_null: bool,
103 pub(crate) unique: bool,
104 pub(crate) primary_key: bool,
105 pub(crate) auto_increment: bool,
106 pub(crate) default: Option<SimpleExpr>,
107 pub(crate) check: Option<SimpleExpr>,
108 pub(crate) comment: Option<String>,
109}
110
111impl ColumnDef {
112 pub fn new<T>(name: T) -> Self
114 where
115 T: IntoIden,
116 {
117 Self {
118 name: name.into_iden(),
119 column_type: None,
120 not_null: false,
121 unique: false,
122 primary_key: false,
123 auto_increment: false,
124 default: None,
125 check: None,
126 comment: None,
127 }
128 }
129
130 pub fn column_type(mut self, column_type: ColumnType) -> Self {
132 self.column_type = Some(column_type);
133 self
134 }
135
136 pub fn not_null(mut self, not_null: bool) -> Self {
138 self.not_null = not_null;
139 self
140 }
141
142 pub fn unique(mut self, unique: bool) -> Self {
144 self.unique = unique;
145 self
146 }
147
148 pub fn primary_key(mut self, primary_key: bool) -> Self {
150 self.primary_key = primary_key;
151 self
152 }
153
154 pub fn auto_increment(mut self, auto_increment: bool) -> Self {
156 self.auto_increment = auto_increment;
157 self
158 }
159
160 pub fn default(mut self, value: SimpleExpr) -> Self {
162 self.default = Some(value);
163 self
164 }
165
166 pub fn check(mut self, expr: SimpleExpr) -> Self {
168 self.check = Some(expr);
169 self
170 }
171
172 pub fn comment<S: Into<String>>(mut self, comment: S) -> Self {
174 self.comment = Some(comment.into());
175 self
176 }
177
178 pub fn integer(self) -> Self {
182 self.column_type(ColumnType::Integer)
183 }
184
185 pub fn big_integer(self) -> Self {
187 self.column_type(ColumnType::BigInteger)
188 }
189
190 pub fn small_integer(self) -> Self {
192 self.column_type(ColumnType::SmallInteger)
193 }
194
195 pub fn tiny_integer(self) -> Self {
197 self.column_type(ColumnType::TinyInteger)
198 }
199
200 pub fn string(self) -> Self {
202 self.column_type(ColumnType::String(None))
203 }
204
205 pub fn string_len(self, len: u32) -> Self {
207 self.column_type(ColumnType::String(Some(len)))
208 }
209
210 pub fn char(self) -> Self {
212 self.column_type(ColumnType::Char(None))
213 }
214
215 pub fn char_len(self, len: u32) -> Self {
217 self.column_type(ColumnType::Char(Some(len)))
218 }
219
220 pub fn text(self) -> Self {
222 self.column_type(ColumnType::Text)
223 }
224
225 pub fn boolean(self) -> Self {
227 self.column_type(ColumnType::Boolean)
228 }
229
230 pub fn float(self) -> Self {
232 self.column_type(ColumnType::Float)
233 }
234
235 pub fn double(self) -> Self {
237 self.column_type(ColumnType::Double)
238 }
239
240 pub fn decimal(self, precision: u32, scale: u32) -> Self {
242 self.column_type(ColumnType::Decimal(Some((precision, scale))))
243 }
244
245 pub fn date(self) -> Self {
247 self.column_type(ColumnType::Date)
248 }
249
250 pub fn time(self) -> Self {
252 self.column_type(ColumnType::Time)
253 }
254
255 pub fn date_time(self) -> Self {
257 self.column_type(ColumnType::DateTime)
258 }
259
260 pub fn timestamp(self) -> Self {
262 self.column_type(ColumnType::Timestamp)
263 }
264
265 pub fn timestamp_with_time_zone(self) -> Self {
267 self.column_type(ColumnType::TimestampWithTimeZone)
268 }
269
270 pub fn uuid(self) -> Self {
272 self.column_type(ColumnType::Uuid)
273 }
274
275 pub fn json(self) -> Self {
277 self.column_type(ColumnType::Json)
278 }
279
280 pub fn json_binary(self) -> Self {
282 self.column_type(ColumnType::JsonBinary)
283 }
284
285 pub fn blob(self) -> Self {
287 self.column_type(ColumnType::Blob)
288 }
289
290 pub fn binary(self, len: u32) -> Self {
292 self.column_type(ColumnType::Binary(Some(len)))
293 }
294
295 pub fn binary_len(self, len: u32) -> Self {
299 self.column_type(ColumnType::Binary(Some(len)))
300 }
301
302 pub fn var_binary(self, len: u32) -> Self {
304 self.column_type(ColumnType::VarBinary(len))
305 }
306
307 pub fn custom<S: Into<String>>(self, name: S) -> Self {
309 self.column_type(ColumnType::Custom(name.into()))
310 }
311
312 pub fn array(self, element_type: ColumnType) -> Self {
314 self.column_type(ColumnType::Array(Box::new(element_type)))
315 }
316}
317
318#[derive(Debug, Clone)]
322#[non_exhaustive]
323pub enum TableConstraint {
324 PrimaryKey {
326 name: Option<DynIden>,
328 columns: Vec<DynIden>,
330 },
331 Unique {
333 name: Option<DynIden>,
335 columns: Vec<DynIden>,
337 },
338 ForeignKey {
340 name: Option<DynIden>,
342 columns: Vec<DynIden>,
344 ref_table: Box<TableRef>,
346 ref_columns: Vec<DynIden>,
348 on_delete: Option<ForeignKeyAction>,
350 on_update: Option<ForeignKeyAction>,
352 },
353 Check {
355 name: Option<DynIden>,
357 expr: SimpleExpr,
359 },
360}
361
362#[derive(Debug, Clone, Copy, PartialEq, Eq)]
366#[non_exhaustive]
367pub enum ForeignKeyAction {
368 Restrict,
370 Cascade,
372 SetNull,
374 SetDefault,
376 NoAction,
378}
379
380impl ForeignKeyAction {
381 pub fn as_str(&self) -> &'static str {
383 match self {
384 Self::Restrict => "RESTRICT",
385 Self::Cascade => "CASCADE",
386 Self::SetNull => "SET NULL",
387 Self::SetDefault => "SET DEFAULT",
388 Self::NoAction => "NO ACTION",
389 }
390 }
391}
392
393#[derive(Debug, Clone)]
401#[allow(dead_code)]
402pub struct IndexDef {
403 pub(crate) name: DynIden,
404 pub(crate) table: TableRef,
405 pub(crate) columns: Vec<DynIden>,
406 pub(crate) unique: bool,
407 pub(crate) r#where: Option<SimpleExpr>,
408}
409
410impl IndexDef {
411 pub fn new<T, R>(name: T, table: R) -> Self
413 where
414 T: IntoIden,
415 R: Into<TableRef>,
416 {
417 Self {
418 name: name.into_iden(),
419 table: table.into(),
420 columns: Vec::new(),
421 unique: false,
422 r#where: None,
423 }
424 }
425
426 pub fn column<C>(mut self, col: C) -> Self
428 where
429 C: IntoIden,
430 {
431 self.columns.push(col.into_iden());
432 self
433 }
434
435 pub fn columns<I, C>(mut self, cols: I) -> Self
437 where
438 I: IntoIterator<Item = C>,
439 C: IntoIden,
440 {
441 for col in cols {
442 self.columns.push(col.into_iden());
443 }
444 self
445 }
446
447 pub fn unique(mut self, unique: bool) -> Self {
449 self.unique = unique;
450 self
451 }
452
453 pub fn r#where(mut self, expr: SimpleExpr) -> Self {
455 self.r#where = Some(expr);
456 self
457 }
458}
459
460#[cfg(test)]
461mod tests {
462 use super::*;
463 use rstest::rstest;
464
465 #[rstest]
466 fn test_column_def_integer() {
467 let col = ColumnDef::new("age").integer().not_null(true);
469
470 assert_eq!(col.column_type, Some(ColumnType::Integer));
472 assert!(col.not_null);
473 }
474
475 #[rstest]
476 fn test_column_def_string_len() {
477 let col = ColumnDef::new("name").string_len(100);
479
480 assert_eq!(col.column_type, Some(ColumnType::String(Some(100))));
482 }
483
484 #[rstest]
485 fn test_column_def_text() {
486 let col = ColumnDef::new("bio").text();
488
489 assert_eq!(col.column_type, Some(ColumnType::Text));
491 }
492
493 #[rstest]
494 fn test_column_def_boolean() {
495 let col = ColumnDef::new("active").boolean();
497
498 assert_eq!(col.column_type, Some(ColumnType::Boolean));
500 }
501
502 #[rstest]
503 fn test_column_def_timestamp() {
504 let col = ColumnDef::new("created_at").timestamp();
506
507 assert_eq!(col.column_type, Some(ColumnType::Timestamp));
509 }
510
511 #[rstest]
512 fn test_column_def_uuid() {
513 let col = ColumnDef::new("id").uuid().primary_key(true);
515
516 assert_eq!(col.column_type, Some(ColumnType::Uuid));
518 assert!(col.primary_key);
519 }
520
521 #[rstest]
522 fn test_column_def_chaining() {
523 let col = ColumnDef::new("email")
525 .string_len(255)
526 .not_null(true)
527 .unique(true);
528
529 assert_eq!(col.column_type, Some(ColumnType::String(Some(255))));
531 assert!(col.not_null);
532 assert!(col.unique);
533 }
534
535 #[rstest]
536 fn test_column_def_json_binary() {
537 let col = ColumnDef::new("data").json_binary();
539
540 assert_eq!(col.column_type, Some(ColumnType::JsonBinary));
542 }
543
544 #[rstest]
545 fn test_column_def_decimal() {
546 let col = ColumnDef::new("price").decimal(10, 2);
548
549 assert_eq!(col.column_type, Some(ColumnType::Decimal(Some((10, 2)))));
551 }
552
553 #[rstest]
554 fn test_column_def_custom() {
555 let col = ColumnDef::new("data").custom("CITEXT");
557
558 assert_eq!(
560 col.column_type,
561 Some(ColumnType::Custom("CITEXT".to_string()))
562 );
563 }
564}