sea_orm_codegen/entity/
column.rs

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