Skip to main content

sea_orm_codegen/entity/
column.rs

1use crate::{BigIntegerType, DateTimeCrate, util::escape_rust_keyword};
2use heck::{ToSnakeCase, ToUpperCamelCase};
3use proc_macro2::{Ident, TokenStream};
4use quote::{format_ident, quote};
5use sea_query::{ColumnDef, ColumnType, StringLen};
6use std::fmt::Write as FmtWrite;
7
8#[derive(Debug, Clone)]
9pub struct Column {
10    pub(crate) name: String,
11    pub(crate) col_type: ColumnType,
12    pub(crate) auto_increment: bool,
13    pub(crate) not_null: bool,
14    pub(crate) unique: bool,
15    pub(crate) unique_key: Option<String>,
16}
17
18#[derive(Debug, Default, Copy, Clone)]
19pub struct ColumnOption {
20    pub(crate) date_time_crate: DateTimeCrate,
21    pub(crate) big_integer_type: BigIntegerType,
22}
23
24impl Column {
25    pub fn get_name_snake_case(&self) -> Ident {
26        format_ident!("{}", escape_rust_keyword(self.name.to_snake_case()))
27    }
28
29    pub fn get_name_camel_case(&self) -> Ident {
30        format_ident!("{}", escape_rust_keyword(self.name.to_upper_camel_case()))
31    }
32
33    pub fn is_snake_case_name(&self) -> bool {
34        self.name.to_snake_case() == self.name
35    }
36
37    pub fn get_rs_type(&self, opt: &ColumnOption) -> TokenStream {
38        fn write_rs_type(col_type: &ColumnType, opt: &ColumnOption) -> String {
39            #[allow(unreachable_patterns)]
40            match col_type {
41                ColumnType::Char(_)
42                | ColumnType::String(_)
43                | ColumnType::Text
44                | ColumnType::Custom(_) => "String".to_owned(),
45                ColumnType::TinyInteger => "i8".to_owned(),
46                ColumnType::SmallInteger => "i16".to_owned(),
47                ColumnType::Integer => "i32".to_owned(),
48                ColumnType::BigInteger => match opt.big_integer_type {
49                    BigIntegerType::I64 => "i64",
50                    BigIntegerType::I32 => "i32",
51                }
52                .to_owned(),
53                ColumnType::TinyUnsigned => "u8".to_owned(),
54                ColumnType::SmallUnsigned => "u16".to_owned(),
55                ColumnType::Unsigned => "u32".to_owned(),
56                ColumnType::BigUnsigned => "u64".to_owned(),
57                ColumnType::Float => "f32".to_owned(),
58                ColumnType::Double => "f64".to_owned(),
59                ColumnType::Json | ColumnType::JsonBinary => "Json".to_owned(),
60                ColumnType::Date => match opt.date_time_crate {
61                    DateTimeCrate::Chrono => "Date".to_owned(),
62                    DateTimeCrate::Time => "TimeDate".to_owned(),
63                },
64                ColumnType::Time => match opt.date_time_crate {
65                    DateTimeCrate::Chrono => "Time".to_owned(),
66                    DateTimeCrate::Time => "TimeTime".to_owned(),
67                },
68                ColumnType::DateTime => match opt.date_time_crate {
69                    DateTimeCrate::Chrono => "DateTime".to_owned(),
70                    DateTimeCrate::Time => "TimeDateTime".to_owned(),
71                },
72                ColumnType::Timestamp => match opt.date_time_crate {
73                    DateTimeCrate::Chrono => "DateTimeUtc".to_owned(),
74                    DateTimeCrate::Time => "TimeDateTime".to_owned(),
75                },
76                ColumnType::TimestampWithTimeZone => match opt.date_time_crate {
77                    DateTimeCrate::Chrono => "DateTimeWithTimeZone".to_owned(),
78                    DateTimeCrate::Time => "TimeDateTimeWithTimeZone".to_owned(),
79                },
80                ColumnType::Decimal(_) | ColumnType::Money(_) => "Decimal".to_owned(),
81                ColumnType::Uuid => "Uuid".to_owned(),
82                ColumnType::Binary(_) | ColumnType::VarBinary(_) | ColumnType::Blob => {
83                    "Vec<u8>".to_owned()
84                }
85                ColumnType::Boolean => "bool".to_owned(),
86                ColumnType::Enum { name, .. } => name.to_string().to_upper_camel_case(),
87                ColumnType::Array(column_type) => {
88                    format!("Vec<{}>", write_rs_type(column_type, opt))
89                }
90                ColumnType::Vector(_) => "PgVector".to_owned(),
91                ColumnType::Bit(None | Some(1)) => "bool".to_owned(),
92                ColumnType::Bit(_) | ColumnType::VarBit(_) => "Vec<u8>".to_owned(),
93                ColumnType::Year => "i32".to_owned(),
94                ColumnType::Cidr | ColumnType::Inet => "IpNetwork".to_owned(),
95                ColumnType::Interval(_, _) | ColumnType::MacAddr | ColumnType::LTree => {
96                    "String".to_owned()
97                }
98                _ => unimplemented!(),
99            }
100        }
101        let ident: TokenStream = write_rs_type(&self.col_type, opt).parse().unwrap();
102        match self.not_null {
103            true => quote! { #ident },
104            false => quote! { Option<#ident> },
105        }
106    }
107
108    pub fn get_col_type_attrs(&self) -> Option<TokenStream> {
109        let col_type = match &self.col_type {
110            ColumnType::Float => Some("Float".to_owned()),
111            ColumnType::Double => Some("Double".to_owned()),
112            ColumnType::Decimal(Some((p, s))) => Some(format!("Decimal(Some(({p}, {s})))")),
113            ColumnType::Money(Some((p, s))) => Some(format!("Money(Some({p}, {s}))")),
114            ColumnType::Text => Some("Text".to_owned()),
115            ColumnType::JsonBinary => Some("JsonBinary".to_owned()),
116            ColumnType::Custom(iden) => {
117                let ty = format!("custom(\"{iden}\")");
118                return Some(quote! ( ignore, column_type = #ty, select_as = "text" ));
119            }
120            ColumnType::Binary(s) => Some(format!("Binary({s})")),
121            ColumnType::VarBinary(s) => match s {
122                StringLen::N(s) => Some(format!("VarBinary(StringLen::N({s}))")),
123                StringLen::None => Some("VarBinary(StringLen::None)".to_owned()),
124                StringLen::Max => Some("VarBinary(StringLen::Max)".to_owned()),
125            },
126            ColumnType::Blob => Some("Blob".to_owned()),
127            ColumnType::Cidr => Some("Cidr".to_owned()),
128            _ => None,
129        };
130        col_type.map(|ty| quote! { column_type = #ty })
131    }
132
133    fn get_def_inner(&self, enum_type_ident: Option<&Ident>) -> TokenStream {
134        fn write_col_def(col_type: &ColumnType, enum_type_ident: Option<&Ident>) -> TokenStream {
135            match col_type {
136                ColumnType::Char(s) => match s {
137                    Some(s) => quote! { ColumnType::Char(Some(#s)) },
138                    None => quote! { ColumnType::Char(None) },
139                },
140                ColumnType::String(s) => match s {
141                    StringLen::N(s) => quote! { ColumnType::String(StringLen::N(#s)) },
142                    StringLen::None => quote! { ColumnType::String(StringLen::None) },
143                    StringLen::Max => quote! { ColumnType::String(StringLen::Max) },
144                },
145                ColumnType::Text => quote! { ColumnType::Text },
146                ColumnType::TinyInteger => quote! { ColumnType::TinyInteger },
147                ColumnType::SmallInteger => quote! { ColumnType::SmallInteger },
148                ColumnType::Integer => quote! { ColumnType::Integer },
149                ColumnType::BigInteger => quote! { ColumnType::BigInteger },
150                ColumnType::TinyUnsigned => quote! { ColumnType::TinyUnsigned },
151                ColumnType::SmallUnsigned => quote! { ColumnType::SmallUnsigned },
152                ColumnType::Unsigned => quote! { ColumnType::Unsigned },
153                ColumnType::BigUnsigned => quote! { ColumnType::BigUnsigned },
154                ColumnType::Float => quote! { ColumnType::Float },
155                ColumnType::Double => quote! { ColumnType::Double },
156                ColumnType::Decimal(s) => match s {
157                    Some((s1, s2)) => quote! { ColumnType::Decimal(Some((#s1, #s2))) },
158                    None => quote! { ColumnType::Decimal(None) },
159                },
160                ColumnType::DateTime => quote! { ColumnType::DateTime },
161                ColumnType::Timestamp => quote! { ColumnType::Timestamp },
162                ColumnType::TimestampWithTimeZone => {
163                    quote! { ColumnType::TimestampWithTimeZone }
164                }
165                ColumnType::Time => quote! { ColumnType::Time },
166                ColumnType::Date => quote! { ColumnType::Date },
167                ColumnType::Binary(s) => {
168                    quote! { ColumnType::Binary(#s) }
169                }
170                ColumnType::VarBinary(s) => match s {
171                    StringLen::N(s) => quote! { ColumnType::VarBinary(StringLen::N(#s)) },
172                    StringLen::None => quote! { ColumnType::VarBinary(StringLen::None) },
173                    StringLen::Max => quote! { ColumnType::VarBinary(StringLen::Max) },
174                },
175                ColumnType::Blob => quote! { ColumnType::Blob },
176                ColumnType::Boolean => quote! { ColumnType::Boolean },
177                ColumnType::Money(s) => match s {
178                    Some((s1, s2)) => quote! { ColumnType::Money(Some((#s1, #s2))) },
179                    None => quote! { ColumnType::Money(None) },
180                },
181                ColumnType::Json => quote! { ColumnType::Json },
182                ColumnType::JsonBinary => quote! { ColumnType::JsonBinary },
183                ColumnType::Uuid => quote! { ColumnType::Uuid },
184                ColumnType::Cidr => quote! { ColumnType::Cidr },
185                ColumnType::Inet => quote! { ColumnType::Inet },
186                ColumnType::Custom(s) => {
187                    let s = s.to_string();
188                    quote! { ColumnType::custom(#s) }
189                }
190                ColumnType::Enum { name, .. } => {
191                    let enum_ident = enum_type_ident.cloned().unwrap_or_else(|| {
192                        format_ident!("{}", name.to_string().to_upper_camel_case())
193                    });
194                    quote! {
195                        #enum_ident::db_type()
196                            .get_column_type()
197                            .to_owned()
198                    }
199                }
200                ColumnType::Array(column_type) => {
201                    let column_type = write_col_def(column_type, enum_type_ident);
202                    quote! { ColumnType::Array(RcOrArc::new(#column_type)) }
203                }
204                ColumnType::Vector(size) => match size {
205                    Some(size) => quote! { ColumnType::Vector(Some(#size)) },
206                    None => quote! { ColumnType::Vector(None) },
207                },
208                #[allow(unreachable_patterns)]
209                _ => unimplemented!(),
210            }
211        }
212        let mut col_def = write_col_def(&self.col_type, enum_type_ident);
213        col_def.extend(quote! {
214            .def()
215        });
216        if !self.not_null {
217            col_def.extend(quote! {
218                .null()
219            });
220        }
221        if self.unique {
222            col_def.extend(quote! {
223                .unique()
224            });
225        }
226        col_def
227    }
228
229    pub fn get_def(&self) -> TokenStream {
230        self.get_def_inner(None)
231    }
232
233    pub fn get_def_with_enum_type_ident(&self, enum_type_ident: &Ident) -> TokenStream {
234        self.get_def_inner(Some(enum_type_ident))
235    }
236
237    pub fn get_info(&self, opt: &ColumnOption) -> String {
238        let mut info = String::new();
239        let type_info = self.get_rs_type(opt).to_string().replace(' ', "");
240        let col_info = self.col_info();
241        write!(
242            &mut info,
243            "Column `{}`: {}{}",
244            self.name, type_info, col_info
245        )
246        .unwrap();
247        info
248    }
249
250    fn col_info(&self) -> String {
251        let mut info = String::new();
252        if self.auto_increment {
253            write!(&mut info, ", auto_increment").unwrap();
254        }
255        if self.not_null {
256            write!(&mut info, ", not_null").unwrap();
257        }
258        if self.unique {
259            write!(&mut info, ", unique").unwrap();
260        }
261        info
262    }
263
264    pub fn get_serde_attribute(
265        &self,
266        is_primary_key: bool,
267        serde_skip_deserializing_primary_key: bool,
268        serde_skip_hidden_column: bool,
269    ) -> TokenStream {
270        if self.name.starts_with('_') && serde_skip_hidden_column {
271            quote! {
272                #[serde(skip)]
273            }
274        } else if serde_skip_deserializing_primary_key && is_primary_key {
275            quote! {
276                #[serde(skip_deserializing)]
277            }
278        } else {
279            quote! {}
280        }
281    }
282
283    pub fn get_inner_col_type(&self) -> &ColumnType {
284        match &self.col_type {
285            ColumnType::Array(inner_col_type) => inner_col_type.as_ref(),
286            _ => &self.col_type,
287        }
288    }
289}
290
291impl From<ColumnDef> for Column {
292    fn from(col_def: ColumnDef) -> Self {
293        (&col_def).into()
294    }
295}
296
297impl From<&ColumnDef> for Column {
298    fn from(col_def: &ColumnDef) -> Self {
299        let name = col_def.get_column_name();
300        let col_type = match col_def.get_column_type() {
301            Some(ty) => ty.clone(),
302            None => panic!("ColumnType should not be empty"),
303        };
304        let auto_increment = col_def.get_column_spec().auto_increment;
305        let not_null = match col_def.get_column_spec().nullable {
306            Some(nullable) => !nullable,
307            None => false,
308        };
309        let unique = col_def.get_column_spec().unique;
310        Self {
311            name,
312            col_type,
313            auto_increment,
314            not_null,
315            unique,
316            unique_key: None,
317        }
318    }
319}
320
321#[cfg(test)]
322mod tests {
323    use crate::{Column, ColumnOption, DateTimeCrate};
324    use proc_macro2::TokenStream;
325    use quote::quote;
326    use sea_query::{Alias, ColumnDef, ColumnType, SeaRc, StringLen};
327
328    fn date_time_crate_chrono() -> ColumnOption {
329        ColumnOption {
330            date_time_crate: DateTimeCrate::Chrono,
331            big_integer_type: Default::default(),
332        }
333    }
334
335    fn date_time_crate_time() -> ColumnOption {
336        ColumnOption {
337            date_time_crate: DateTimeCrate::Time,
338            big_integer_type: Default::default(),
339        }
340    }
341
342    fn setup() -> Vec<Column> {
343        macro_rules! make_col {
344            ($name:expr, $col_type:expr) => {
345                Column {
346                    name: $name.to_owned(),
347                    col_type: $col_type,
348                    auto_increment: false,
349                    not_null: false,
350                    unique: false,
351                    unique_key: None,
352                }
353            };
354        }
355        vec![
356            make_col!("id", ColumnType::String(StringLen::N(255))),
357            make_col!("id", ColumnType::String(StringLen::None)),
358            make_col!(
359                "cake_id",
360                ColumnType::Custom(SeaRc::new(Alias::new("cus_col")))
361            ),
362            make_col!("CakeId", ColumnType::TinyInteger),
363            make_col!("CakeId", ColumnType::TinyUnsigned),
364            make_col!("CakeId", ColumnType::SmallInteger),
365            make_col!("CakeId", ColumnType::SmallUnsigned),
366            make_col!("CakeId", ColumnType::Integer),
367            make_col!("CakeId", ColumnType::Unsigned),
368            make_col!("CakeFillingId", ColumnType::BigInteger),
369            make_col!("CakeFillingId", ColumnType::BigUnsigned),
370            make_col!("cake-filling-id", ColumnType::Float),
371            make_col!("CAKE_FILLING_ID", ColumnType::Double),
372            make_col!("CAKE-FILLING-ID", ColumnType::Binary(10)),
373            make_col!("CAKE-FILLING-ID", ColumnType::VarBinary(StringLen::None)),
374            make_col!("CAKE-FILLING-ID", ColumnType::VarBinary(StringLen::N(10))),
375            make_col!("CAKE-FILLING-ID", ColumnType::VarBinary(StringLen::Max)),
376            make_col!("CAKE", ColumnType::Boolean),
377            make_col!("date", ColumnType::Date),
378            make_col!("time", ColumnType::Time),
379            make_col!("date_time", ColumnType::DateTime),
380            make_col!("timestamp", ColumnType::Timestamp),
381            make_col!("timestamp_tz", ColumnType::TimestampWithTimeZone),
382        ]
383    }
384
385    #[test]
386    fn test_get_name_snake_case() {
387        let columns = setup();
388        let snack_cases = vec![
389            "id",
390            "id",
391            "cake_id",
392            "cake_id",
393            "cake_id",
394            "cake_id",
395            "cake_id",
396            "cake_id",
397            "cake_id",
398            "cake_filling_id",
399            "cake_filling_id",
400            "cake_filling_id",
401            "cake_filling_id",
402            "cake_filling_id",
403            "cake_filling_id",
404            "cake_filling_id",
405            "cake_filling_id",
406            "cake",
407            "date",
408            "time",
409            "date_time",
410            "timestamp",
411            "timestamp_tz",
412        ];
413        for (col, snack_case) in columns.into_iter().zip(snack_cases) {
414            assert_eq!(col.get_name_snake_case().to_string(), snack_case);
415        }
416    }
417
418    #[test]
419    fn test_get_name_camel_case() {
420        let columns = setup();
421        let camel_cases = vec![
422            "Id",
423            "Id",
424            "CakeId",
425            "CakeId",
426            "CakeId",
427            "CakeId",
428            "CakeId",
429            "CakeId",
430            "CakeId",
431            "CakeFillingId",
432            "CakeFillingId",
433            "CakeFillingId",
434            "CakeFillingId",
435            "CakeFillingId",
436            "CakeFillingId",
437            "CakeFillingId",
438            "CakeFillingId",
439            "Cake",
440            "Date",
441            "Time",
442            "DateTime",
443            "Timestamp",
444            "TimestampTz",
445        ];
446        for (col, camel_case) in columns.into_iter().zip(camel_cases) {
447            assert_eq!(col.get_name_camel_case().to_string(), camel_case);
448        }
449    }
450
451    #[test]
452    fn test_get_rs_type_with_chrono() {
453        let columns = setup();
454        let rs_types = vec![
455            "String",
456            "String",
457            "String",
458            "i8",
459            "u8",
460            "i16",
461            "u16",
462            "i32",
463            "u32",
464            "i64",
465            "u64",
466            "f32",
467            "f64",
468            "Vec<u8>",
469            "Vec<u8>",
470            "Vec<u8>",
471            "Vec<u8>",
472            "bool",
473            "Date",
474            "Time",
475            "DateTime",
476            "DateTimeUtc",
477            "DateTimeWithTimeZone",
478        ];
479        for (mut col, rs_type) in columns.into_iter().zip(rs_types) {
480            let rs_type: TokenStream = rs_type.parse().unwrap();
481
482            col.not_null = true;
483            assert_eq!(
484                col.get_rs_type(&date_time_crate_chrono()).to_string(),
485                quote!(#rs_type).to_string()
486            );
487
488            col.not_null = false;
489            assert_eq!(
490                col.get_rs_type(&date_time_crate_chrono()).to_string(),
491                quote!(Option<#rs_type>).to_string()
492            );
493        }
494    }
495
496    #[test]
497    fn test_get_rs_type_with_time() {
498        let columns = setup();
499        let rs_types = vec![
500            "String",
501            "String",
502            "String",
503            "i8",
504            "u8",
505            "i16",
506            "u16",
507            "i32",
508            "u32",
509            "i64",
510            "u64",
511            "f32",
512            "f64",
513            "Vec<u8>",
514            "Vec<u8>",
515            "Vec<u8>",
516            "Vec<u8>",
517            "bool",
518            "TimeDate",
519            "TimeTime",
520            "TimeDateTime",
521            "TimeDateTime",
522            "TimeDateTimeWithTimeZone",
523        ];
524        for (mut col, rs_type) in columns.into_iter().zip(rs_types) {
525            let rs_type: TokenStream = rs_type.parse().unwrap();
526
527            col.not_null = true;
528            assert_eq!(
529                col.get_rs_type(&date_time_crate_time()).to_string(),
530                quote!(#rs_type).to_string()
531            );
532
533            col.not_null = false;
534            assert_eq!(
535                col.get_rs_type(&date_time_crate_time()).to_string(),
536                quote!(Option<#rs_type>).to_string()
537            );
538        }
539    }
540
541    #[test]
542    fn test_get_def() {
543        let columns = setup();
544        let col_defs = vec![
545            "ColumnType::String(StringLen::N(255u32)).def()",
546            "ColumnType::String(StringLen::None).def()",
547            "ColumnType::custom(\"cus_col\").def()",
548            "ColumnType::TinyInteger.def()",
549            "ColumnType::TinyUnsigned.def()",
550            "ColumnType::SmallInteger.def()",
551            "ColumnType::SmallUnsigned.def()",
552            "ColumnType::Integer.def()",
553            "ColumnType::Unsigned.def()",
554            "ColumnType::BigInteger.def()",
555            "ColumnType::BigUnsigned.def()",
556            "ColumnType::Float.def()",
557            "ColumnType::Double.def()",
558            "ColumnType::Binary(10u32).def()",
559            "ColumnType::VarBinary(StringLen::None).def()",
560            "ColumnType::VarBinary(StringLen::N(10u32)).def()",
561            "ColumnType::VarBinary(StringLen::Max).def()",
562            "ColumnType::Boolean.def()",
563            "ColumnType::Date.def()",
564            "ColumnType::Time.def()",
565            "ColumnType::DateTime.def()",
566            "ColumnType::Timestamp.def()",
567            "ColumnType::TimestampWithTimeZone.def()",
568        ];
569        for (mut col, col_def) in columns.into_iter().zip(col_defs) {
570            let mut col_def: TokenStream = col_def.parse().unwrap();
571
572            col.not_null = true;
573            assert_eq!(col.get_def().to_string(), col_def.to_string());
574
575            col.not_null = false;
576            col_def.extend(quote!(.null()));
577            assert_eq!(col.get_def().to_string(), col_def.to_string());
578
579            col.unique = true;
580            col_def.extend(quote!(.unique()));
581            assert_eq!(col.get_def().to_string(), col_def.to_string());
582        }
583    }
584
585    #[test]
586    fn test_get_info() {
587        let column: Column = ColumnDef::new(Alias::new("id")).string().to_owned().into();
588        assert_eq!(
589            column.get_info(&date_time_crate_chrono()).as_str(),
590            "Column `id`: Option<String>"
591        );
592
593        let column: Column = ColumnDef::new(Alias::new("id"))
594            .string()
595            .not_null()
596            .to_owned()
597            .into();
598        assert_eq!(
599            column.get_info(&date_time_crate_chrono()).as_str(),
600            "Column `id`: String, not_null"
601        );
602
603        let column: Column = ColumnDef::new(Alias::new("id"))
604            .string()
605            .not_null()
606            .unique_key()
607            .to_owned()
608            .into();
609        assert_eq!(
610            column.get_info(&date_time_crate_chrono()).as_str(),
611            "Column `id`: String, not_null, unique"
612        );
613
614        let column: Column = ColumnDef::new(Alias::new("id"))
615            .string()
616            .not_null()
617            .unique_key()
618            .auto_increment()
619            .to_owned()
620            .into();
621        assert_eq!(
622            column.get_info(&date_time_crate_chrono()).as_str(),
623            "Column `id`: String, auto_increment, not_null, unique"
624        );
625
626        let column: Column = ColumnDef::new(Alias::new("date_field"))
627            .date()
628            .not_null()
629            .to_owned()
630            .into();
631        assert_eq!(
632            column.get_info(&date_time_crate_chrono()).as_str(),
633            "Column `date_field`: Date, not_null"
634        );
635
636        let column: Column = ColumnDef::new(Alias::new("date_field"))
637            .date()
638            .not_null()
639            .to_owned()
640            .into();
641        assert_eq!(
642            column.get_info(&date_time_crate_time()).as_str(),
643            "Column `date_field`: TimeDate, not_null"
644        );
645
646        let column: Column = ColumnDef::new(Alias::new("time_field"))
647            .time()
648            .not_null()
649            .to_owned()
650            .into();
651        assert_eq!(
652            column.get_info(&date_time_crate_chrono()).as_str(),
653            "Column `time_field`: Time, not_null"
654        );
655
656        let column: Column = ColumnDef::new(Alias::new("time_field"))
657            .time()
658            .not_null()
659            .to_owned()
660            .into();
661        assert_eq!(
662            column.get_info(&date_time_crate_time()).as_str(),
663            "Column `time_field`: TimeTime, not_null"
664        );
665
666        let column: Column = ColumnDef::new(Alias::new("date_time_field"))
667            .date_time()
668            .not_null()
669            .to_owned()
670            .into();
671        assert_eq!(
672            column.get_info(&date_time_crate_chrono()).as_str(),
673            "Column `date_time_field`: DateTime, not_null"
674        );
675
676        let column: Column = ColumnDef::new(Alias::new("date_time_field"))
677            .date_time()
678            .not_null()
679            .to_owned()
680            .into();
681        assert_eq!(
682            column.get_info(&date_time_crate_time()).as_str(),
683            "Column `date_time_field`: TimeDateTime, not_null"
684        );
685
686        let column: Column = ColumnDef::new(Alias::new("timestamp_field"))
687            .timestamp()
688            .not_null()
689            .to_owned()
690            .into();
691        assert_eq!(
692            column.get_info(&date_time_crate_chrono()).as_str(),
693            "Column `timestamp_field`: DateTimeUtc, not_null"
694        );
695
696        let column: Column = ColumnDef::new(Alias::new("timestamp_field"))
697            .timestamp()
698            .not_null()
699            .to_owned()
700            .into();
701        assert_eq!(
702            column.get_info(&date_time_crate_time()).as_str(),
703            "Column `timestamp_field`: TimeDateTime, not_null"
704        );
705
706        let column: Column = ColumnDef::new(Alias::new("timestamp_with_timezone_field"))
707            .timestamp_with_time_zone()
708            .not_null()
709            .to_owned()
710            .into();
711        assert_eq!(
712            column.get_info(&date_time_crate_chrono()).as_str(),
713            "Column `timestamp_with_timezone_field`: DateTimeWithTimeZone, not_null"
714        );
715
716        let column: Column = ColumnDef::new(Alias::new("timestamp_with_timezone_field"))
717            .timestamp_with_time_zone()
718            .not_null()
719            .to_owned()
720            .into();
721        assert_eq!(
722            column.get_info(&date_time_crate_time()).as_str(),
723            "Column `timestamp_with_timezone_field`: TimeDateTimeWithTimeZone, not_null"
724        );
725    }
726
727    #[test]
728    fn test_from_column_def() {
729        let column: Column = ColumnDef::new(Alias::new("id")).string().to_owned().into();
730        assert_eq!(
731            column.get_def().to_string(),
732            quote! {
733                ColumnType::String(StringLen::None).def().null()
734            }
735            .to_string()
736        );
737
738        let column: Column = ColumnDef::new(Alias::new("id"))
739            .string()
740            .not_null()
741            .to_owned()
742            .into();
743        assert!(column.not_null);
744
745        let column: Column = ColumnDef::new(Alias::new("id"))
746            .string()
747            .unique_key()
748            .not_null()
749            .to_owned()
750            .into();
751        assert!(column.unique);
752        assert!(column.not_null);
753
754        let column: Column = ColumnDef::new(Alias::new("id"))
755            .string()
756            .auto_increment()
757            .unique_key()
758            .not_null()
759            .to_owned()
760            .into();
761        assert!(column.auto_increment);
762        assert!(column.unique);
763        assert!(column.not_null);
764    }
765}