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    pub fn get_def(&self) -> TokenStream {
134        fn write_col_def(col_type: &ColumnType) -> 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 = format_ident!("{}", name.to_string().to_upper_camel_case());
192                    quote! {
193                        #enum_ident::db_type()
194                            .get_column_type()
195                            .to_owned()
196                    }
197                }
198                ColumnType::Array(column_type) => {
199                    let column_type = write_col_def(column_type);
200                    quote! { ColumnType::Array(RcOrArc::new(#column_type)) }
201                }
202                ColumnType::Vector(size) => match size {
203                    Some(size) => quote! { ColumnType::Vector(Some(#size)) },
204                    None => quote! { ColumnType::Vector(None) },
205                },
206                #[allow(unreachable_patterns)]
207                _ => unimplemented!(),
208            }
209        }
210        let mut col_def = write_col_def(&self.col_type);
211        col_def.extend(quote! {
212            .def()
213        });
214        if !self.not_null {
215            col_def.extend(quote! {
216                .null()
217            });
218        }
219        if self.unique {
220            col_def.extend(quote! {
221                .unique()
222            });
223        }
224        col_def
225    }
226
227    pub fn get_info(&self, opt: &ColumnOption) -> String {
228        let mut info = String::new();
229        let type_info = self.get_rs_type(opt).to_string().replace(' ', "");
230        let col_info = self.col_info();
231        write!(
232            &mut info,
233            "Column `{}`: {}{}",
234            self.name, type_info, col_info
235        )
236        .unwrap();
237        info
238    }
239
240    fn col_info(&self) -> String {
241        let mut info = String::new();
242        if self.auto_increment {
243            write!(&mut info, ", auto_increment").unwrap();
244        }
245        if self.not_null {
246            write!(&mut info, ", not_null").unwrap();
247        }
248        if self.unique {
249            write!(&mut info, ", unique").unwrap();
250        }
251        info
252    }
253
254    pub fn get_serde_attribute(
255        &self,
256        is_primary_key: bool,
257        serde_skip_deserializing_primary_key: bool,
258        serde_skip_hidden_column: bool,
259    ) -> TokenStream {
260        if self.name.starts_with('_') && serde_skip_hidden_column {
261            quote! {
262                #[serde(skip)]
263            }
264        } else if serde_skip_deserializing_primary_key && is_primary_key {
265            quote! {
266                #[serde(skip_deserializing)]
267            }
268        } else {
269            quote! {}
270        }
271    }
272
273    pub fn get_inner_col_type(&self) -> &ColumnType {
274        match &self.col_type {
275            ColumnType::Array(inner_col_type) => inner_col_type.as_ref(),
276            _ => &self.col_type,
277        }
278    }
279}
280
281impl From<ColumnDef> for Column {
282    fn from(col_def: ColumnDef) -> Self {
283        (&col_def).into()
284    }
285}
286
287impl From<&ColumnDef> for Column {
288    fn from(col_def: &ColumnDef) -> Self {
289        let name = col_def.get_column_name();
290        let col_type = match col_def.get_column_type() {
291            Some(ty) => ty.clone(),
292            None => panic!("ColumnType should not be empty"),
293        };
294        let auto_increment = col_def.get_column_spec().auto_increment;
295        let not_null = match col_def.get_column_spec().nullable {
296            Some(nullable) => !nullable,
297            None => false,
298        };
299        let unique = col_def.get_column_spec().unique;
300        Self {
301            name,
302            col_type,
303            auto_increment,
304            not_null,
305            unique,
306            unique_key: None,
307        }
308    }
309}
310
311#[cfg(test)]
312mod tests {
313    use crate::{Column, ColumnOption, DateTimeCrate};
314    use proc_macro2::TokenStream;
315    use quote::quote;
316    use sea_query::{Alias, ColumnDef, ColumnType, SeaRc, StringLen};
317
318    fn date_time_crate_chrono() -> ColumnOption {
319        ColumnOption {
320            date_time_crate: DateTimeCrate::Chrono,
321            big_integer_type: Default::default(),
322        }
323    }
324
325    fn date_time_crate_time() -> ColumnOption {
326        ColumnOption {
327            date_time_crate: DateTimeCrate::Time,
328            big_integer_type: Default::default(),
329        }
330    }
331
332    fn setup() -> Vec<Column> {
333        macro_rules! make_col {
334            ($name:expr, $col_type:expr) => {
335                Column {
336                    name: $name.to_owned(),
337                    col_type: $col_type,
338                    auto_increment: false,
339                    not_null: false,
340                    unique: false,
341                    unique_key: None,
342                }
343            };
344        }
345        vec![
346            make_col!("id", ColumnType::String(StringLen::N(255))),
347            make_col!("id", ColumnType::String(StringLen::None)),
348            make_col!(
349                "cake_id",
350                ColumnType::Custom(SeaRc::new(Alias::new("cus_col")))
351            ),
352            make_col!("CakeId", ColumnType::TinyInteger),
353            make_col!("CakeId", ColumnType::TinyUnsigned),
354            make_col!("CakeId", ColumnType::SmallInteger),
355            make_col!("CakeId", ColumnType::SmallUnsigned),
356            make_col!("CakeId", ColumnType::Integer),
357            make_col!("CakeId", ColumnType::Unsigned),
358            make_col!("CakeFillingId", ColumnType::BigInteger),
359            make_col!("CakeFillingId", ColumnType::BigUnsigned),
360            make_col!("cake-filling-id", ColumnType::Float),
361            make_col!("CAKE_FILLING_ID", ColumnType::Double),
362            make_col!("CAKE-FILLING-ID", ColumnType::Binary(10)),
363            make_col!("CAKE-FILLING-ID", ColumnType::VarBinary(StringLen::None)),
364            make_col!("CAKE-FILLING-ID", ColumnType::VarBinary(StringLen::N(10))),
365            make_col!("CAKE-FILLING-ID", ColumnType::VarBinary(StringLen::Max)),
366            make_col!("CAKE", ColumnType::Boolean),
367            make_col!("date", ColumnType::Date),
368            make_col!("time", ColumnType::Time),
369            make_col!("date_time", ColumnType::DateTime),
370            make_col!("timestamp", ColumnType::Timestamp),
371            make_col!("timestamp_tz", ColumnType::TimestampWithTimeZone),
372        ]
373    }
374
375    #[test]
376    fn test_get_name_snake_case() {
377        let columns = setup();
378        let snack_cases = vec![
379            "id",
380            "id",
381            "cake_id",
382            "cake_id",
383            "cake_id",
384            "cake_id",
385            "cake_id",
386            "cake_id",
387            "cake_id",
388            "cake_filling_id",
389            "cake_filling_id",
390            "cake_filling_id",
391            "cake_filling_id",
392            "cake_filling_id",
393            "cake_filling_id",
394            "cake_filling_id",
395            "cake_filling_id",
396            "cake",
397            "date",
398            "time",
399            "date_time",
400            "timestamp",
401            "timestamp_tz",
402        ];
403        for (col, snack_case) in columns.into_iter().zip(snack_cases) {
404            assert_eq!(col.get_name_snake_case().to_string(), snack_case);
405        }
406    }
407
408    #[test]
409    fn test_get_name_camel_case() {
410        let columns = setup();
411        let camel_cases = vec![
412            "Id",
413            "Id",
414            "CakeId",
415            "CakeId",
416            "CakeId",
417            "CakeId",
418            "CakeId",
419            "CakeId",
420            "CakeId",
421            "CakeFillingId",
422            "CakeFillingId",
423            "CakeFillingId",
424            "CakeFillingId",
425            "CakeFillingId",
426            "CakeFillingId",
427            "CakeFillingId",
428            "CakeFillingId",
429            "Cake",
430            "Date",
431            "Time",
432            "DateTime",
433            "Timestamp",
434            "TimestampTz",
435        ];
436        for (col, camel_case) in columns.into_iter().zip(camel_cases) {
437            assert_eq!(col.get_name_camel_case().to_string(), camel_case);
438        }
439    }
440
441    #[test]
442    fn test_get_rs_type_with_chrono() {
443        let columns = setup();
444        let rs_types = vec![
445            "String",
446            "String",
447            "String",
448            "i8",
449            "u8",
450            "i16",
451            "u16",
452            "i32",
453            "u32",
454            "i64",
455            "u64",
456            "f32",
457            "f64",
458            "Vec<u8>",
459            "Vec<u8>",
460            "Vec<u8>",
461            "Vec<u8>",
462            "bool",
463            "Date",
464            "Time",
465            "DateTime",
466            "DateTimeUtc",
467            "DateTimeWithTimeZone",
468        ];
469        for (mut col, rs_type) in columns.into_iter().zip(rs_types) {
470            let rs_type: TokenStream = rs_type.parse().unwrap();
471
472            col.not_null = true;
473            assert_eq!(
474                col.get_rs_type(&date_time_crate_chrono()).to_string(),
475                quote!(#rs_type).to_string()
476            );
477
478            col.not_null = false;
479            assert_eq!(
480                col.get_rs_type(&date_time_crate_chrono()).to_string(),
481                quote!(Option<#rs_type>).to_string()
482            );
483        }
484    }
485
486    #[test]
487    fn test_get_rs_type_with_time() {
488        let columns = setup();
489        let rs_types = vec![
490            "String",
491            "String",
492            "String",
493            "i8",
494            "u8",
495            "i16",
496            "u16",
497            "i32",
498            "u32",
499            "i64",
500            "u64",
501            "f32",
502            "f64",
503            "Vec<u8>",
504            "Vec<u8>",
505            "Vec<u8>",
506            "Vec<u8>",
507            "bool",
508            "TimeDate",
509            "TimeTime",
510            "TimeDateTime",
511            "TimeDateTime",
512            "TimeDateTimeWithTimeZone",
513        ];
514        for (mut col, rs_type) in columns.into_iter().zip(rs_types) {
515            let rs_type: TokenStream = rs_type.parse().unwrap();
516
517            col.not_null = true;
518            assert_eq!(
519                col.get_rs_type(&date_time_crate_time()).to_string(),
520                quote!(#rs_type).to_string()
521            );
522
523            col.not_null = false;
524            assert_eq!(
525                col.get_rs_type(&date_time_crate_time()).to_string(),
526                quote!(Option<#rs_type>).to_string()
527            );
528        }
529    }
530
531    #[test]
532    fn test_get_def() {
533        let columns = setup();
534        let col_defs = vec![
535            "ColumnType::String(StringLen::N(255u32)).def()",
536            "ColumnType::String(StringLen::None).def()",
537            "ColumnType::custom(\"cus_col\").def()",
538            "ColumnType::TinyInteger.def()",
539            "ColumnType::TinyUnsigned.def()",
540            "ColumnType::SmallInteger.def()",
541            "ColumnType::SmallUnsigned.def()",
542            "ColumnType::Integer.def()",
543            "ColumnType::Unsigned.def()",
544            "ColumnType::BigInteger.def()",
545            "ColumnType::BigUnsigned.def()",
546            "ColumnType::Float.def()",
547            "ColumnType::Double.def()",
548            "ColumnType::Binary(10u32).def()",
549            "ColumnType::VarBinary(StringLen::None).def()",
550            "ColumnType::VarBinary(StringLen::N(10u32)).def()",
551            "ColumnType::VarBinary(StringLen::Max).def()",
552            "ColumnType::Boolean.def()",
553            "ColumnType::Date.def()",
554            "ColumnType::Time.def()",
555            "ColumnType::DateTime.def()",
556            "ColumnType::Timestamp.def()",
557            "ColumnType::TimestampWithTimeZone.def()",
558        ];
559        for (mut col, col_def) in columns.into_iter().zip(col_defs) {
560            let mut col_def: TokenStream = col_def.parse().unwrap();
561
562            col.not_null = true;
563            assert_eq!(col.get_def().to_string(), col_def.to_string());
564
565            col.not_null = false;
566            col_def.extend(quote!(.null()));
567            assert_eq!(col.get_def().to_string(), col_def.to_string());
568
569            col.unique = true;
570            col_def.extend(quote!(.unique()));
571            assert_eq!(col.get_def().to_string(), col_def.to_string());
572        }
573    }
574
575    #[test]
576    fn test_get_info() {
577        let column: Column = ColumnDef::new(Alias::new("id")).string().to_owned().into();
578        assert_eq!(
579            column.get_info(&date_time_crate_chrono()).as_str(),
580            "Column `id`: Option<String>"
581        );
582
583        let column: Column = ColumnDef::new(Alias::new("id"))
584            .string()
585            .not_null()
586            .to_owned()
587            .into();
588        assert_eq!(
589            column.get_info(&date_time_crate_chrono()).as_str(),
590            "Column `id`: String, not_null"
591        );
592
593        let column: Column = ColumnDef::new(Alias::new("id"))
594            .string()
595            .not_null()
596            .unique_key()
597            .to_owned()
598            .into();
599        assert_eq!(
600            column.get_info(&date_time_crate_chrono()).as_str(),
601            "Column `id`: String, not_null, unique"
602        );
603
604        let column: Column = ColumnDef::new(Alias::new("id"))
605            .string()
606            .not_null()
607            .unique_key()
608            .auto_increment()
609            .to_owned()
610            .into();
611        assert_eq!(
612            column.get_info(&date_time_crate_chrono()).as_str(),
613            "Column `id`: String, auto_increment, not_null, unique"
614        );
615
616        let column: Column = ColumnDef::new(Alias::new("date_field"))
617            .date()
618            .not_null()
619            .to_owned()
620            .into();
621        assert_eq!(
622            column.get_info(&date_time_crate_chrono()).as_str(),
623            "Column `date_field`: Date, not_null"
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_time()).as_str(),
633            "Column `date_field`: TimeDate, not_null"
634        );
635
636        let column: Column = ColumnDef::new(Alias::new("time_field"))
637            .time()
638            .not_null()
639            .to_owned()
640            .into();
641        assert_eq!(
642            column.get_info(&date_time_crate_chrono()).as_str(),
643            "Column `time_field`: Time, 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_time()).as_str(),
653            "Column `time_field`: TimeTime, not_null"
654        );
655
656        let column: Column = ColumnDef::new(Alias::new("date_time_field"))
657            .date_time()
658            .not_null()
659            .to_owned()
660            .into();
661        assert_eq!(
662            column.get_info(&date_time_crate_chrono()).as_str(),
663            "Column `date_time_field`: DateTime, 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_time()).as_str(),
673            "Column `date_time_field`: TimeDateTime, not_null"
674        );
675
676        let column: Column = ColumnDef::new(Alias::new("timestamp_field"))
677            .timestamp()
678            .not_null()
679            .to_owned()
680            .into();
681        assert_eq!(
682            column.get_info(&date_time_crate_chrono()).as_str(),
683            "Column `timestamp_field`: DateTimeUtc, 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_time()).as_str(),
693            "Column `timestamp_field`: TimeDateTime, not_null"
694        );
695
696        let column: Column = ColumnDef::new(Alias::new("timestamp_with_timezone_field"))
697            .timestamp_with_time_zone()
698            .not_null()
699            .to_owned()
700            .into();
701        assert_eq!(
702            column.get_info(&date_time_crate_chrono()).as_str(),
703            "Column `timestamp_with_timezone_field`: DateTimeWithTimeZone, 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_time()).as_str(),
713            "Column `timestamp_with_timezone_field`: TimeDateTimeWithTimeZone, not_null"
714        );
715    }
716
717    #[test]
718    fn test_from_column_def() {
719        let column: Column = ColumnDef::new(Alias::new("id")).string().to_owned().into();
720        assert_eq!(
721            column.get_def().to_string(),
722            quote! {
723                ColumnType::String(StringLen::None).def().null()
724            }
725            .to_string()
726        );
727
728        let column: Column = ColumnDef::new(Alias::new("id"))
729            .string()
730            .not_null()
731            .to_owned()
732            .into();
733        assert!(column.not_null);
734
735        let column: Column = ColumnDef::new(Alias::new("id"))
736            .string()
737            .unique_key()
738            .not_null()
739            .to_owned()
740            .into();
741        assert!(column.unique);
742        assert!(column.not_null);
743
744        let column: Column = ColumnDef::new(Alias::new("id"))
745            .string()
746            .auto_increment()
747            .unique_key()
748            .not_null()
749            .to_owned()
750            .into();
751        assert!(column.auto_increment);
752        assert!(column.unique);
753        assert!(column.not_null);
754    }
755}