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