sea_orm_codegen/entity/
column.rs

1use crate::{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(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    pub(crate) unique_key: Option<String>,
16}
17
18impl Column {
19    pub fn get_name_snake_case(&self) -> Ident {
20        format_ident!("{}", escape_rust_keyword(self.name.to_snake_case()))
21    }
22
23    pub fn get_name_camel_case(&self) -> Ident {
24        format_ident!("{}", escape_rust_keyword(self.name.to_upper_camel_case()))
25    }
26
27    pub fn is_snake_case_name(&self) -> bool {
28        self.name.to_snake_case() == self.name
29    }
30
31    pub fn get_rs_type(&self, date_time_crate: &DateTimeCrate) -> TokenStream {
32        fn write_rs_type(col_type: &ColumnType, date_time_crate: &DateTimeCrate) -> String {
33            #[allow(unreachable_patterns)]
34            match col_type {
35                ColumnType::Char(_)
36                | ColumnType::String(_)
37                | ColumnType::Text
38                | ColumnType::Custom(_) => "String".to_owned(),
39                ColumnType::TinyInteger => "i8".to_owned(),
40                ColumnType::SmallInteger => "i16".to_owned(),
41                ColumnType::Integer => "i32".to_owned(),
42                ColumnType::BigInteger => "i64".to_owned(),
43                ColumnType::TinyUnsigned => "u8".to_owned(),
44                ColumnType::SmallUnsigned => "u16".to_owned(),
45                ColumnType::Unsigned => "u32".to_owned(),
46                ColumnType::BigUnsigned => "u64".to_owned(),
47                ColumnType::Float => "f32".to_owned(),
48                ColumnType::Double => "f64".to_owned(),
49                ColumnType::Json | ColumnType::JsonBinary => "Json".to_owned(),
50                ColumnType::Date => match date_time_crate {
51                    DateTimeCrate::Chrono => "Date".to_owned(),
52                    DateTimeCrate::Time => "TimeDate".to_owned(),
53                },
54                ColumnType::Time => match date_time_crate {
55                    DateTimeCrate::Chrono => "Time".to_owned(),
56                    DateTimeCrate::Time => "TimeTime".to_owned(),
57                },
58                ColumnType::DateTime => match date_time_crate {
59                    DateTimeCrate::Chrono => "DateTime".to_owned(),
60                    DateTimeCrate::Time => "TimeDateTime".to_owned(),
61                },
62                ColumnType::Timestamp => match date_time_crate {
63                    DateTimeCrate::Chrono => "DateTimeUtc".to_owned(),
64                    DateTimeCrate::Time => "TimeDateTime".to_owned(),
65                },
66                ColumnType::TimestampWithTimeZone => match date_time_crate {
67                    DateTimeCrate::Chrono => "DateTimeWithTimeZone".to_owned(),
68                    DateTimeCrate::Time => "TimeDateTimeWithTimeZone".to_owned(),
69                },
70                ColumnType::Decimal(_) | ColumnType::Money(_) => "Decimal".to_owned(),
71                ColumnType::Uuid => "Uuid".to_owned(),
72                ColumnType::Binary(_) | ColumnType::VarBinary(_) | ColumnType::Blob => {
73                    "Vec<u8>".to_owned()
74                }
75                ColumnType::Boolean => "bool".to_owned(),
76                ColumnType::Enum { name, .. } => name.to_string().to_upper_camel_case(),
77                ColumnType::Array(column_type) => {
78                    format!("Vec<{}>", write_rs_type(column_type, date_time_crate))
79                }
80                ColumnType::Vector(_) => "PgVector".to_owned(),
81                ColumnType::Bit(None | Some(1)) => "bool".to_owned(),
82                ColumnType::Bit(_) | ColumnType::VarBit(_) => "Vec<u8>".to_owned(),
83                ColumnType::Year => "i32".to_owned(),
84                ColumnType::Cidr | ColumnType::Inet => "IpNetwork".to_owned(),
85                ColumnType::Interval(_, _) | ColumnType::MacAddr | ColumnType::LTree => {
86                    "String".to_owned()
87                }
88                _ => unimplemented!(),
89            }
90        }
91        let ident: TokenStream = write_rs_type(&self.col_type, date_time_crate)
92            .parse()
93            .unwrap();
94        match self.not_null {
95            true => quote! { #ident },
96            false => quote! { Option<#ident> },
97        }
98    }
99
100    pub fn get_col_type_attrs(&self) -> Option<TokenStream> {
101        let col_type = match &self.col_type {
102            ColumnType::Float => Some("Float".to_owned()),
103            ColumnType::Double => Some("Double".to_owned()),
104            ColumnType::Decimal(Some((p, s))) => Some(format!("Decimal(Some(({p}, {s})))")),
105            ColumnType::Money(Some((p, s))) => Some(format!("Money(Some({p}, {s}))")),
106            ColumnType::Text => Some("Text".to_owned()),
107            ColumnType::JsonBinary => Some("JsonBinary".to_owned()),
108            ColumnType::Custom(iden) => {
109                let ty = format!("custom(\"{iden}\")");
110                return Some(quote! ( ignore, column_type = #ty, select_as = "text" ));
111            }
112            ColumnType::Binary(s) => Some(format!("Binary({s})")),
113            ColumnType::VarBinary(s) => match s {
114                StringLen::N(s) => Some(format!("VarBinary(StringLen::N({s}))")),
115                StringLen::None => Some("VarBinary(StringLen::None)".to_owned()),
116                StringLen::Max => Some("VarBinary(StringLen::Max)".to_owned()),
117            },
118            ColumnType::Blob => Some("Blob".to_owned()),
119            ColumnType::Cidr => Some("Cidr".to_owned()),
120            _ => None,
121        };
122        col_type.map(|ty| quote! { column_type = #ty })
123    }
124
125    pub fn get_def(&self) -> TokenStream {
126        fn write_col_def(col_type: &ColumnType) -> TokenStream {
127            match col_type {
128                ColumnType::Char(s) => match s {
129                    Some(s) => quote! { ColumnType::Char(Some(#s)) },
130                    None => quote! { ColumnType::Char(None) },
131                },
132                ColumnType::String(s) => match s {
133                    StringLen::N(s) => quote! { ColumnType::String(StringLen::N(#s)) },
134                    StringLen::None => quote! { ColumnType::String(StringLen::None) },
135                    StringLen::Max => quote! { ColumnType::String(StringLen::Max) },
136                },
137                ColumnType::Text => quote! { ColumnType::Text },
138                ColumnType::TinyInteger => quote! { ColumnType::TinyInteger },
139                ColumnType::SmallInteger => quote! { ColumnType::SmallInteger },
140                ColumnType::Integer => quote! { ColumnType::Integer },
141                ColumnType::BigInteger => quote! { ColumnType::BigInteger },
142                ColumnType::TinyUnsigned => quote! { ColumnType::TinyUnsigned },
143                ColumnType::SmallUnsigned => quote! { ColumnType::SmallUnsigned },
144                ColumnType::Unsigned => quote! { ColumnType::Unsigned },
145                ColumnType::BigUnsigned => quote! { ColumnType::BigUnsigned },
146                ColumnType::Float => quote! { ColumnType::Float },
147                ColumnType::Double => quote! { ColumnType::Double },
148                ColumnType::Decimal(s) => match s {
149                    Some((s1, s2)) => quote! { ColumnType::Decimal(Some((#s1, #s2))) },
150                    None => quote! { ColumnType::Decimal(None) },
151                },
152                ColumnType::DateTime => quote! { ColumnType::DateTime },
153                ColumnType::Timestamp => quote! { ColumnType::Timestamp },
154                ColumnType::TimestampWithTimeZone => {
155                    quote! { ColumnType::TimestampWithTimeZone }
156                }
157                ColumnType::Time => quote! { ColumnType::Time },
158                ColumnType::Date => quote! { ColumnType::Date },
159                ColumnType::Binary(s) => {
160                    quote! { ColumnType::Binary(#s) }
161                }
162                ColumnType::VarBinary(s) => match s {
163                    StringLen::N(s) => quote! { ColumnType::VarBinary(StringLen::N(#s)) },
164                    StringLen::None => quote! { ColumnType::VarBinary(StringLen::None) },
165                    StringLen::Max => quote! { ColumnType::VarBinary(StringLen::Max) },
166                },
167                ColumnType::Blob => quote! { ColumnType::Blob },
168                ColumnType::Boolean => quote! { ColumnType::Boolean },
169                ColumnType::Money(s) => match s {
170                    Some((s1, s2)) => quote! { ColumnType::Money(Some((#s1, #s2))) },
171                    None => quote! { ColumnType::Money(None) },
172                },
173                ColumnType::Json => quote! { ColumnType::Json },
174                ColumnType::JsonBinary => quote! { ColumnType::JsonBinary },
175                ColumnType::Uuid => quote! { ColumnType::Uuid },
176                ColumnType::Cidr => quote! { ColumnType::Cidr },
177                ColumnType::Inet => quote! { ColumnType::Inet },
178                ColumnType::Custom(s) => {
179                    let s = s.to_string();
180                    quote! { ColumnType::custom(#s) }
181                }
182                ColumnType::Enum { name, .. } => {
183                    let enum_ident = format_ident!("{}", name.to_string().to_upper_camel_case());
184                    quote! {
185                        #enum_ident::db_type()
186                            .get_column_type()
187                            .to_owned()
188                    }
189                }
190                ColumnType::Array(column_type) => {
191                    let column_type = write_col_def(column_type);
192                    quote! { ColumnType::Array(RcOrArc::new(#column_type)) }
193                }
194                ColumnType::Vector(size) => match size {
195                    Some(size) => quote! { ColumnType::Vector(Some(#size)) },
196                    None => quote! { ColumnType::Vector(None) },
197                },
198                #[allow(unreachable_patterns)]
199                _ => unimplemented!(),
200            }
201        }
202        let mut col_def = write_col_def(&self.col_type);
203        col_def.extend(quote! {
204            .def()
205        });
206        if !self.not_null {
207            col_def.extend(quote! {
208                .null()
209            });
210        }
211        if self.unique {
212            col_def.extend(quote! {
213                .unique()
214            });
215        }
216        col_def
217    }
218
219    pub fn get_info(&self, date_time_crate: &DateTimeCrate) -> String {
220        let mut info = String::new();
221        let type_info = self
222            .get_rs_type(date_time_crate)
223            .to_string()
224            .replace(' ', "");
225        let col_info = self.col_info();
226        write!(
227            &mut info,
228            "Column `{}`: {}{}",
229            self.name, type_info, col_info
230        )
231        .unwrap();
232        info
233    }
234
235    fn col_info(&self) -> String {
236        let mut info = String::new();
237        if self.auto_increment {
238            write!(&mut info, ", auto_increment").unwrap();
239        }
240        if self.not_null {
241            write!(&mut info, ", not_null").unwrap();
242        }
243        if self.unique {
244            write!(&mut info, ", unique").unwrap();
245        }
246        info
247    }
248
249    pub fn get_serde_attribute(
250        &self,
251        is_primary_key: bool,
252        serde_skip_deserializing_primary_key: bool,
253        serde_skip_hidden_column: bool,
254    ) -> TokenStream {
255        if self.name.starts_with('_') && serde_skip_hidden_column {
256            quote! {
257                #[serde(skip)]
258            }
259        } else if serde_skip_deserializing_primary_key && is_primary_key {
260            quote! {
261                #[serde(skip_deserializing)]
262            }
263        } else {
264            quote! {}
265        }
266    }
267
268    pub fn get_inner_col_type(&self) -> &ColumnType {
269        match &self.col_type {
270            ColumnType::Array(inner_col_type) => inner_col_type.as_ref(),
271            _ => &self.col_type,
272        }
273    }
274}
275
276impl From<ColumnDef> for Column {
277    fn from(col_def: ColumnDef) -> Self {
278        (&col_def).into()
279    }
280}
281
282impl From<&ColumnDef> for Column {
283    fn from(col_def: &ColumnDef) -> Self {
284        let name = col_def.get_column_name();
285        let col_type = match col_def.get_column_type() {
286            Some(ty) => ty.clone(),
287            None => panic!("ColumnType should not be empty"),
288        };
289        let auto_increment = col_def.get_column_spec().auto_increment;
290        let not_null = match col_def.get_column_spec().nullable {
291            Some(nullable) => !nullable,
292            None => false,
293        };
294        let unique = col_def.get_column_spec().unique;
295        Self {
296            name,
297            col_type,
298            auto_increment,
299            not_null,
300            unique,
301            unique_key: None,
302        }
303    }
304}
305
306#[cfg(test)]
307mod tests {
308    use crate::{Column, DateTimeCrate};
309    use proc_macro2::TokenStream;
310    use quote::quote;
311    use sea_query::{Alias, ColumnDef, ColumnType, SeaRc, StringLen};
312
313    fn setup() -> Vec<Column> {
314        macro_rules! make_col {
315            ($name:expr, $col_type:expr) => {
316                Column {
317                    name: $name.to_owned(),
318                    col_type: $col_type,
319                    auto_increment: false,
320                    not_null: false,
321                    unique: false,
322                    unique_key: None,
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}