sea_orm/entity/
column_def.rs

1use sea_query::{SimpleExpr, Value};
2
3// The original `sea_orm::ColumnType` enum was dropped since 0.11.0
4// It was replaced by `sea_query::ColumnType`, we reexport it here to keep the `ColumnType` symbol
5pub use sea_query::ColumnType;
6
7/// Defines a Column for an Entity
8#[derive(Debug, Clone, PartialEq)]
9pub struct ColumnDef {
10    pub(crate) col_type: ColumnType,
11    pub(crate) null: bool,
12    pub(crate) unique: bool,
13    pub(crate) indexed: bool,
14    pub(crate) default: Option<SimpleExpr>,
15    pub(crate) comment: Option<String>,
16    pub(crate) unique_key: Option<String>,
17    pub(crate) renamed_from: Option<String>,
18    pub(crate) extra: Option<String>,
19    pub(crate) seaography: SeaographyColumnAttr,
20}
21
22/// Seaography specific attributes
23#[non_exhaustive]
24#[derive(Debug, Default, Clone, PartialEq)]
25pub struct SeaographyColumnAttr {
26    /// Ignore this column in seaography
27    pub ignore: bool,
28}
29
30impl ColumnDef {
31    /// Marks the column as `UNIQUE`
32    pub fn unique(mut self) -> Self {
33        self.unique = true;
34        self
35    }
36
37    /// Set Seaography ignore
38    pub fn seaography_ignore(mut self) -> Self {
39        self.seaography.ignore = true;
40        self
41    }
42
43    /// This column belongs to a unique key
44    pub fn unique_key(mut self, key: &str) -> Self {
45        self.unique_key = Some(key.into());
46        self
47    }
48
49    /// This column is renamed from a previous name
50    pub fn renamed_from(mut self, col: &str) -> Self {
51        self.renamed_from = Some(col.into());
52        self
53    }
54
55    /// Set column comment
56    pub fn comment(mut self, v: &str) -> Self {
57        self.comment = Some(v.into());
58        self
59    }
60
61    /// Mark the column as nullable
62    pub fn null(self) -> Self {
63        self.nullable()
64    }
65
66    /// Mark the column as nullable
67    pub fn nullable(mut self) -> Self {
68        self.null = true;
69        self
70    }
71
72    /// Set the `indexed` field  to `true`
73    pub fn indexed(mut self) -> Self {
74        self.indexed = true;
75        self
76    }
77
78    /// Set the default value
79    pub fn default_value<T>(mut self, value: T) -> Self
80    where
81        T: Into<Value>,
82    {
83        self.default = Some(value.into().into());
84        self
85    }
86
87    /// Set the default value or expression of a column
88    pub fn default<T>(mut self, default: T) -> Self
89    where
90        T: Into<SimpleExpr>,
91    {
92        self.default = Some(default.into());
93        self
94    }
95
96    /// Set the extra SQL string for the column (e.g. "COLLATE NOCASE")
97    pub fn extra(mut self, value: &str) -> Self {
98        self.extra = Some(value.into());
99        self
100    }
101
102    /// Get [ColumnType] as reference
103    pub fn get_column_type(&self) -> &ColumnType {
104        &self.col_type
105    }
106
107    /// Get [Option<SimpleExpr>] as reference
108    pub fn get_column_default(&self) -> Option<&SimpleExpr> {
109        self.default.as_ref()
110    }
111
112    /// Returns true if the column is nullable
113    pub fn is_null(&self) -> bool {
114        self.null
115    }
116
117    /// Returns true if the column is unique
118    pub fn is_unique(&self) -> bool {
119        self.unique
120    }
121
122    /// Get Seaography attribute
123    pub fn seaography(&self) -> &SeaographyColumnAttr {
124        &self.seaography
125    }
126}
127
128#[cfg(test)]
129mod tests {
130    use crate::tests_cfg::*;
131
132    #[test]
133    fn test_col_from_str() {
134        use crate::IdenStatic;
135        use std::str::FromStr;
136
137        assert!(matches!(
138            fruit::Column::from_str("id"),
139            Ok(fruit::Column::Id)
140        ));
141        assert!(matches!(
142            fruit::Column::from_str("name"),
143            Ok(fruit::Column::Name)
144        ));
145        assert!(matches!(
146            fruit::Column::from_str("cake_id"),
147            Ok(fruit::Column::CakeId)
148        ));
149        assert!(matches!(
150            fruit::Column::from_str("cakeId"),
151            Ok(fruit::Column::CakeId)
152        ));
153        assert!(matches!(
154            fruit::Column::from_str("CakeId"),
155            Err(crate::ColumnFromStrErr(_))
156        ));
157        assert!(matches!(
158            fruit::Column::from_str("does_not_exist"),
159            Err(crate::ColumnFromStrErr(_))
160        ));
161        assert!(matches!(fruit::Column::CakeId.as_str(), "cake_id"));
162    }
163
164    #[test]
165    #[cfg(feature = "macros")]
166    fn entity_model_column_1() {
167        use crate::prelude::*;
168
169        mod hello {
170            use crate as sea_orm;
171            use crate::entity::prelude::*;
172
173            #[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
174            #[sea_orm(table_name = "hello")]
175            pub struct Model {
176                #[sea_orm(primary_key)]
177                pub id: i32,
178                pub one: i32,
179                #[sea_orm(unique)]
180                pub two: i8,
181                #[sea_orm(indexed)]
182                pub three: i16,
183                #[sea_orm(nullable)]
184                pub four: i32,
185                #[sea_orm(unique, indexed, nullable)]
186                pub five: i64,
187                #[sea_orm(unique)]
188                pub six: u8,
189                #[sea_orm(indexed)]
190                pub seven: u16,
191                #[sea_orm(nullable)]
192                pub eight: u32,
193                #[sea_orm(unique, indexed, nullable)]
194                pub nine: u64,
195                #[sea_orm(default_expr = "Expr::current_timestamp()")]
196                pub ten: DateTimeUtc,
197                #[sea_orm(default_value = 7)]
198                pub eleven: u8,
199                #[sea_orm(default_value = "twelve_value")]
200                pub twelve: String,
201                #[sea_orm(default_expr = "\"twelve_value\"")]
202                pub twelve_two: String,
203            }
204
205            #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
206            pub enum Relation {}
207
208            impl ActiveModelBehavior for ActiveModel {}
209        }
210
211        assert_eq!(hello::Column::One.def(), ColumnType::Integer.def());
212        assert_eq!(
213            hello::Column::Two.def(),
214            ColumnType::TinyInteger.def().unique()
215        );
216        assert_eq!(
217            hello::Column::Three.def(),
218            ColumnType::SmallInteger.def().indexed()
219        );
220        assert_eq!(
221            hello::Column::Four.def(),
222            ColumnType::Integer.def().nullable()
223        );
224        assert_eq!(
225            hello::Column::Five.def(),
226            ColumnType::BigInteger.def().unique().indexed().nullable()
227        );
228        assert_eq!(
229            hello::Column::Six.def(),
230            ColumnType::TinyUnsigned.def().unique()
231        );
232        assert_eq!(
233            hello::Column::Seven.def(),
234            ColumnType::SmallUnsigned.def().indexed()
235        );
236        assert_eq!(
237            hello::Column::Eight.def(),
238            ColumnType::Unsigned.def().nullable()
239        );
240        assert_eq!(
241            hello::Column::Nine.def(),
242            ColumnType::BigUnsigned.def().unique().indexed().nullable()
243        );
244        assert_eq!(
245            hello::Column::Ten.def(),
246            ColumnType::TimestampWithTimeZone
247                .def()
248                .default(Expr::current_timestamp())
249        );
250        assert_eq!(
251            hello::Column::Eleven.def(),
252            ColumnType::TinyUnsigned.def().default(7)
253        );
254        assert_eq!(
255            hello::Column::Twelve.def(),
256            ColumnType::String(StringLen::None)
257                .def()
258                .default("twelve_value")
259        );
260        assert_eq!(
261            hello::Column::TwelveTwo.def(),
262            ColumnType::String(StringLen::None)
263                .def()
264                .default("twelve_value")
265        );
266    }
267
268    #[test]
269    #[cfg(feature = "macros")]
270    fn column_name_1() {
271        use crate::ColumnTrait;
272        use sea_query::Iden;
273
274        mod hello {
275            use crate as sea_orm;
276            use crate::entity::prelude::*;
277
278            #[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
279            #[sea_orm(table_name = "hello")]
280            pub struct Model {
281                #[sea_orm(primary_key)]
282                pub id: i32,
283                #[sea_orm(column_name = "ONE")]
284                pub one: i32,
285                #[seaography(ignore)]
286                pub two: i32,
287                #[sea_orm(column_name = "3")]
288                #[seaography(ignore)]
289                pub three: i32,
290            }
291
292            #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
293            pub enum Relation {}
294
295            impl ActiveModelBehavior for ActiveModel {}
296        }
297
298        assert_eq!(hello::Column::One.to_string().as_str(), "ONE");
299        assert_eq!(hello::Column::Two.to_string().as_str(), "two");
300        assert_eq!(hello::Column::Three.to_string().as_str(), "3");
301
302        assert!(!hello::Column::One.def().seaography().ignore);
303        assert!(hello::Column::Two.def().seaography().ignore);
304        assert!(hello::Column::Three.def().seaography().ignore);
305    }
306
307    #[test]
308    #[cfg(feature = "macros")]
309    fn column_name_2() {
310        use sea_query::Iden;
311
312        mod hello {
313            use crate as sea_orm;
314            use crate::entity::prelude::*;
315
316            #[derive(Copy, Clone, Default, Debug, DeriveEntity)]
317            pub struct Entity;
318
319            impl EntityName for Entity {
320                fn table_name(&self) -> &'static str {
321                    "hello"
322                }
323            }
324
325            #[derive(Clone, Debug, PartialEq, Eq, DeriveModel, DeriveActiveModel)]
326            pub struct Model {
327                pub id: i32,
328                pub one: i32,
329                pub two: i32,
330                pub three: i32,
331            }
332
333            #[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)]
334            pub enum Column {
335                Id,
336                #[sea_orm(column_name = "ONE")]
337                One,
338                Two,
339                #[sea_orm(column_name = "3")]
340                Three,
341            }
342
343            impl ColumnTrait for Column {
344                type EntityName = Entity;
345
346                fn def(&self) -> ColumnDef {
347                    match self {
348                        Column::Id => ColumnType::Integer.def(),
349                        Column::One => ColumnType::Integer.def(),
350                        Column::Two => ColumnType::Integer.def(),
351                        Column::Three => ColumnType::Integer.def(),
352                    }
353                }
354            }
355
356            #[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)]
357            pub enum PrimaryKey {
358                Id,
359            }
360
361            impl PrimaryKeyTrait for PrimaryKey {
362                type ValueType = i32;
363
364                fn auto_increment() -> bool {
365                    true
366                }
367            }
368
369            #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
370            pub enum Relation {}
371
372            impl ActiveModelBehavior for ActiveModel {}
373        }
374
375        assert_eq!(hello::Column::One.to_string().as_str(), "ONE");
376        assert_eq!(hello::Column::Two.to_string().as_str(), "two");
377        assert_eq!(hello::Column::Three.to_string().as_str(), "3");
378    }
379
380    #[test]
381    #[cfg(feature = "macros")]
382    fn enum_name_1() {
383        use sea_query::Iden;
384
385        mod hello {
386            use crate as sea_orm;
387            use crate::entity::prelude::*;
388
389            #[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
390            #[sea_orm(table_name = "hello")]
391            pub struct Model {
392                #[sea_orm(primary_key)]
393                pub id: i32,
394                #[sea_orm(enum_name = "One1")]
395                pub one: i32,
396                pub two: i32,
397                #[sea_orm(enum_name = "Three3")]
398                pub three: i32,
399            }
400
401            #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
402            pub enum Relation {}
403
404            impl ActiveModelBehavior for ActiveModel {}
405        }
406
407        assert_eq!(hello::Column::One1.to_string().as_str(), "one1");
408        assert_eq!(hello::Column::Two.to_string().as_str(), "two");
409        assert_eq!(hello::Column::Three3.to_string().as_str(), "three3");
410    }
411
412    #[test]
413    #[cfg(feature = "macros")]
414    fn enum_name_2() {
415        use sea_query::Iden;
416
417        mod hello {
418            use crate as sea_orm;
419            use crate::entity::prelude::*;
420
421            #[derive(Copy, Clone, Default, Debug, DeriveEntity)]
422            pub struct Entity;
423
424            impl EntityName for Entity {
425                fn table_name(&self) -> &'static str {
426                    "hello"
427                }
428            }
429
430            #[derive(Clone, Debug, PartialEq, Eq, DeriveModel, DeriveActiveModel)]
431            pub struct Model {
432                pub id: i32,
433                #[sea_orm(enum_name = "One1")]
434                pub one: i32,
435                pub two: i32,
436                #[sea_orm(enum_name = "Three3")]
437                pub three: i32,
438            }
439
440            #[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)]
441            pub enum Column {
442                Id,
443                One1,
444                Two,
445                Three3,
446            }
447
448            impl ColumnTrait for Column {
449                type EntityName = Entity;
450
451                fn def(&self) -> ColumnDef {
452                    match self {
453                        Column::Id => ColumnType::Integer.def(),
454                        Column::One1 => ColumnType::Integer.def(),
455                        Column::Two => ColumnType::Integer.def(),
456                        Column::Three3 => ColumnType::Integer.def(),
457                    }
458                }
459            }
460
461            #[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)]
462            pub enum PrimaryKey {
463                Id,
464            }
465
466            impl PrimaryKeyTrait for PrimaryKey {
467                type ValueType = i32;
468
469                fn auto_increment() -> bool {
470                    true
471                }
472            }
473
474            #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
475            pub enum Relation {}
476
477            impl ActiveModelBehavior for ActiveModel {}
478        }
479
480        assert_eq!(hello::Column::One1.to_string().as_str(), "one1");
481        assert_eq!(hello::Column::Two.to_string().as_str(), "two");
482        assert_eq!(hello::Column::Three3.to_string().as_str(), "three3");
483    }
484
485    #[test]
486    #[cfg(feature = "macros")]
487    fn column_name_enum_name_1() {
488        use sea_query::Iden;
489
490        #[allow(clippy::enum_variant_names)]
491        mod hello {
492            use crate as sea_orm;
493            use crate::entity::prelude::*;
494
495            #[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
496            #[sea_orm(table_name = "hello")]
497            pub struct Model {
498                #[sea_orm(primary_key, column_name = "ID", enum_name = "IdentityColumn")]
499                pub id: i32,
500                #[sea_orm(column_name = "ONE", enum_name = "One1")]
501                pub one: i32,
502                pub two: i32,
503                #[sea_orm(column_name = "THREE", enum_name = "Three3")]
504                pub three: i32,
505            }
506
507            #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
508            pub enum Relation {}
509
510            impl ActiveModelBehavior for ActiveModel {}
511        }
512
513        assert_eq!(hello::Column::IdentityColumn.to_string().as_str(), "ID");
514        assert_eq!(hello::Column::One1.to_string().as_str(), "ONE");
515        assert_eq!(hello::Column::Two.to_string().as_str(), "two");
516        assert_eq!(hello::Column::Three3.to_string().as_str(), "THREE");
517    }
518
519    #[test]
520    #[cfg(feature = "macros")]
521    fn column_name_enum_name_2() {
522        use sea_query::Iden;
523
524        mod hello {
525            use crate as sea_orm;
526            use crate::entity::prelude::*;
527
528            #[derive(Copy, Clone, Default, Debug, DeriveEntity)]
529            pub struct Entity;
530
531            impl EntityName for Entity {
532                fn table_name(&self) -> &'static str {
533                    "hello"
534                }
535            }
536
537            #[derive(Clone, Debug, PartialEq, Eq, DeriveModel, DeriveActiveModel)]
538            pub struct Model {
539                #[sea_orm(enum_name = "IdentityCol")]
540                pub id: i32,
541                #[sea_orm(enum_name = "One1")]
542                pub one: i32,
543                pub two: i32,
544                #[sea_orm(enum_name = "Three3")]
545                pub three: i32,
546            }
547
548            #[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)]
549            pub enum Column {
550                #[sea_orm(column_name = "ID")]
551                IdentityCol,
552                #[sea_orm(column_name = "ONE")]
553                One1,
554                Two,
555                #[sea_orm(column_name = "THREE")]
556                Three3,
557            }
558
559            impl ColumnTrait for Column {
560                type EntityName = Entity;
561
562                fn def(&self) -> ColumnDef {
563                    match self {
564                        Column::IdentityCol => ColumnType::Integer.def(),
565                        Column::One1 => ColumnType::Integer.def(),
566                        Column::Two => ColumnType::Integer.def(),
567                        Column::Three3 => ColumnType::Integer.def(),
568                    }
569                }
570            }
571
572            #[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)]
573            pub enum PrimaryKey {
574                IdentityCol,
575            }
576
577            impl PrimaryKeyTrait for PrimaryKey {
578                type ValueType = i32;
579
580                fn auto_increment() -> bool {
581                    true
582                }
583            }
584
585            #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
586            pub enum Relation {}
587
588            impl ActiveModelBehavior for ActiveModel {}
589        }
590
591        assert_eq!(hello::Column::IdentityCol.to_string().as_str(), "ID");
592        assert_eq!(hello::Column::One1.to_string().as_str(), "ONE");
593        assert_eq!(hello::Column::Two.to_string().as_str(), "two");
594        assert_eq!(hello::Column::Three3.to_string().as_str(), "THREE");
595    }
596
597    #[test]
598    #[cfg(feature = "macros")]
599    fn column_name_enum_name_3() {
600        use sea_query::Iden;
601
602        mod my_entity {
603            use crate as sea_orm;
604            use crate::entity::prelude::*;
605
606            #[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
607            #[sea_orm(table_name = "my_entity")]
608            pub struct Model {
609                #[sea_orm(primary_key, enum_name = "IdentityColumn", column_name = "id")]
610                pub id: i32,
611                #[sea_orm(column_name = "type")]
612                pub type_: String,
613            }
614
615            #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
616            pub enum Relation {}
617
618            impl ActiveModelBehavior for ActiveModel {}
619        }
620
621        assert_eq!(my_entity::Column::IdentityColumn.to_string().as_str(), "id");
622        assert_eq!(my_entity::Column::Type.to_string().as_str(), "type");
623    }
624
625    #[test]
626    #[cfg(feature = "macros")]
627    fn column_def_unique_key() {
628        use crate as sea_orm;
629        use crate::entity::prelude::*;
630
631        #[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
632        #[sea_orm(table_name = "my_entity")]
633        pub struct Model {
634            #[sea_orm(primary_key)]
635            pub id: i32,
636            #[sea_orm(column_name = "my_a", unique_key = "my_unique")]
637            pub a: String,
638            #[sea_orm(unique_key = "my_unique")]
639            pub b: String,
640        }
641
642        #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
643        pub enum Relation {}
644
645        impl ActiveModelBehavior for ActiveModel {}
646
647        assert_eq!(
648            Column::A.def(),
649            ColumnType::string(None).def().unique_key("my_unique")
650        );
651        assert_eq!(
652            Column::B.def(),
653            ColumnType::string(None).def().unique_key("my_unique")
654        );
655    }
656
657    #[test]
658    #[cfg(feature = "macros")]
659    fn column_def_renamed_from() {
660        use crate as sea_orm;
661        use crate::entity::prelude::*;
662
663        #[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
664        #[sea_orm(table_name = "my_entity")]
665        pub struct Model {
666            #[sea_orm(primary_key)]
667            pub id: i32,
668            #[sea_orm(column_name = "new_a", renamed_from = "old_a")]
669            pub a: String,
670            #[sea_orm(renamed_from = "old_b")]
671            pub b: String,
672        }
673
674        #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
675        pub enum Relation {}
676
677        impl ActiveModelBehavior for ActiveModel {}
678
679        assert_eq!(Column::A.to_string(), "new_a");
680        assert_eq!(Column::B.to_string(), "b");
681
682        assert_eq!(
683            Column::A.def(),
684            ColumnType::string(None).def().renamed_from("old_a")
685        );
686        assert_eq!(
687            Column::B.def(),
688            ColumnType::string(None).def().renamed_from("old_b")
689        );
690    }
691}