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) => Some(format!("custom(\"{iden}\")")),
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.get_column_spec().auto_increment;
286        let not_null = match col_def.get_column_spec().nullable {
287            Some(nullable) => !nullable,
288            None => false,
289        };
290        let unique = col_def.get_column_spec().unique;
291        Self {
292            name,
293            col_type,
294            auto_increment,
295            not_null,
296            unique,
297        }
298    }
299}
300
301#[cfg(test)]
302mod tests {
303    use crate::{Column, DateTimeCrate};
304    use proc_macro2::TokenStream;
305    use quote::quote;
306    use sea_query::{Alias, ColumnDef, ColumnType, SeaRc, StringLen};
307
308    fn setup() -> Vec<Column> {
309        macro_rules! make_col {
310            ($name:expr, $col_type:expr) => {
311                Column {
312                    name: $name.to_owned(),
313                    col_type: $col_type,
314                    auto_increment: false,
315                    not_null: false,
316                    unique: false,
317                }
318            };
319        }
320        vec![
321            make_col!("id", ColumnType::String(StringLen::N(255))),
322            make_col!("id", ColumnType::String(StringLen::None)),
323            make_col!(
324                "cake_id",
325                ColumnType::Custom(SeaRc::new(Alias::new("cus_col")))
326            ),
327            make_col!("CakeId", ColumnType::TinyInteger),
328            make_col!("CakeId", ColumnType::TinyUnsigned),
329            make_col!("CakeId", ColumnType::SmallInteger),
330            make_col!("CakeId", ColumnType::SmallUnsigned),
331            make_col!("CakeId", ColumnType::Integer),
332            make_col!("CakeId", ColumnType::Unsigned),
333            make_col!("CakeFillingId", ColumnType::BigInteger),
334            make_col!("CakeFillingId", ColumnType::BigUnsigned),
335            make_col!("cake-filling-id", ColumnType::Float),
336            make_col!("CAKE_FILLING_ID", ColumnType::Double),
337            make_col!("CAKE-FILLING-ID", ColumnType::Binary(10)),
338            make_col!("CAKE-FILLING-ID", ColumnType::VarBinary(StringLen::None)),
339            make_col!("CAKE-FILLING-ID", ColumnType::VarBinary(StringLen::N(10))),
340            make_col!("CAKE-FILLING-ID", ColumnType::VarBinary(StringLen::Max)),
341            make_col!("CAKE", ColumnType::Boolean),
342            make_col!("date", ColumnType::Date),
343            make_col!("time", ColumnType::Time),
344            make_col!("date_time", ColumnType::DateTime),
345            make_col!("timestamp", ColumnType::Timestamp),
346            make_col!("timestamp_tz", ColumnType::TimestampWithTimeZone),
347        ]
348    }
349
350    #[test]
351    fn test_get_name_snake_case() {
352        let columns = setup();
353        let snack_cases = vec![
354            "id",
355            "id",
356            "cake_id",
357            "cake_id",
358            "cake_id",
359            "cake_id",
360            "cake_id",
361            "cake_id",
362            "cake_id",
363            "cake_filling_id",
364            "cake_filling_id",
365            "cake_filling_id",
366            "cake_filling_id",
367            "cake_filling_id",
368            "cake_filling_id",
369            "cake_filling_id",
370            "cake_filling_id",
371            "cake",
372            "date",
373            "time",
374            "date_time",
375            "timestamp",
376            "timestamp_tz",
377        ];
378        for (col, snack_case) in columns.into_iter().zip(snack_cases) {
379            assert_eq!(col.get_name_snake_case().to_string(), snack_case);
380        }
381    }
382
383    #[test]
384    fn test_get_name_camel_case() {
385        let columns = setup();
386        let camel_cases = vec![
387            "Id",
388            "Id",
389            "CakeId",
390            "CakeId",
391            "CakeId",
392            "CakeId",
393            "CakeId",
394            "CakeId",
395            "CakeId",
396            "CakeFillingId",
397            "CakeFillingId",
398            "CakeFillingId",
399            "CakeFillingId",
400            "CakeFillingId",
401            "CakeFillingId",
402            "CakeFillingId",
403            "CakeFillingId",
404            "Cake",
405            "Date",
406            "Time",
407            "DateTime",
408            "Timestamp",
409            "TimestampTz",
410        ];
411        for (col, camel_case) in columns.into_iter().zip(camel_cases) {
412            assert_eq!(col.get_name_camel_case().to_string(), camel_case);
413        }
414    }
415
416    #[test]
417    fn test_get_rs_type_with_chrono() {
418        let columns = setup();
419        let chrono_crate = DateTimeCrate::Chrono;
420        let rs_types = vec![
421            "String",
422            "String",
423            "String",
424            "i8",
425            "u8",
426            "i16",
427            "u16",
428            "i32",
429            "u32",
430            "i64",
431            "u64",
432            "f32",
433            "f64",
434            "Vec<u8>",
435            "Vec<u8>",
436            "Vec<u8>",
437            "Vec<u8>",
438            "bool",
439            "Date",
440            "Time",
441            "DateTime",
442            "DateTimeUtc",
443            "DateTimeWithTimeZone",
444        ];
445        for (mut col, rs_type) in columns.into_iter().zip(rs_types) {
446            let rs_type: TokenStream = rs_type.parse().unwrap();
447
448            col.not_null = true;
449            assert_eq!(
450                col.get_rs_type(&chrono_crate).to_string(),
451                quote!(#rs_type).to_string()
452            );
453
454            col.not_null = false;
455            assert_eq!(
456                col.get_rs_type(&chrono_crate).to_string(),
457                quote!(Option<#rs_type>).to_string()
458            );
459        }
460    }
461
462    #[test]
463    fn test_get_rs_type_with_time() {
464        let columns = setup();
465        let time_crate = DateTimeCrate::Time;
466        let rs_types = vec![
467            "String",
468            "String",
469            "String",
470            "i8",
471            "u8",
472            "i16",
473            "u16",
474            "i32",
475            "u32",
476            "i64",
477            "u64",
478            "f32",
479            "f64",
480            "Vec<u8>",
481            "Vec<u8>",
482            "Vec<u8>",
483            "Vec<u8>",
484            "bool",
485            "TimeDate",
486            "TimeTime",
487            "TimeDateTime",
488            "TimeDateTime",
489            "TimeDateTimeWithTimeZone",
490        ];
491        for (mut col, rs_type) in columns.into_iter().zip(rs_types) {
492            let rs_type: TokenStream = rs_type.parse().unwrap();
493
494            col.not_null = true;
495            assert_eq!(
496                col.get_rs_type(&time_crate).to_string(),
497                quote!(#rs_type).to_string()
498            );
499
500            col.not_null = false;
501            assert_eq!(
502                col.get_rs_type(&time_crate).to_string(),
503                quote!(Option<#rs_type>).to_string()
504            );
505        }
506    }
507
508    #[test]
509    fn test_get_def() {
510        let columns = setup();
511        let col_defs = vec![
512            "ColumnType::String(StringLen::N(255u32)).def()",
513            "ColumnType::String(StringLen::None).def()",
514            "ColumnType::custom(\"cus_col\").def()",
515            "ColumnType::TinyInteger.def()",
516            "ColumnType::TinyUnsigned.def()",
517            "ColumnType::SmallInteger.def()",
518            "ColumnType::SmallUnsigned.def()",
519            "ColumnType::Integer.def()",
520            "ColumnType::Unsigned.def()",
521            "ColumnType::BigInteger.def()",
522            "ColumnType::BigUnsigned.def()",
523            "ColumnType::Float.def()",
524            "ColumnType::Double.def()",
525            "ColumnType::Binary(10u32).def()",
526            "ColumnType::VarBinary(StringLen::None).def()",
527            "ColumnType::VarBinary(StringLen::N(10u32)).def()",
528            "ColumnType::VarBinary(StringLen::Max).def()",
529            "ColumnType::Boolean.def()",
530            "ColumnType::Date.def()",
531            "ColumnType::Time.def()",
532            "ColumnType::DateTime.def()",
533            "ColumnType::Timestamp.def()",
534            "ColumnType::TimestampWithTimeZone.def()",
535        ];
536        for (mut col, col_def) in columns.into_iter().zip(col_defs) {
537            let mut col_def: TokenStream = col_def.parse().unwrap();
538
539            col.not_null = true;
540            assert_eq!(col.get_def().to_string(), col_def.to_string());
541
542            col.not_null = false;
543            col_def.extend(quote!(.null()));
544            assert_eq!(col.get_def().to_string(), col_def.to_string());
545
546            col.unique = true;
547            col_def.extend(quote!(.unique()));
548            assert_eq!(col.get_def().to_string(), col_def.to_string());
549        }
550    }
551
552    #[test]
553    fn test_get_info() {
554        let column: Column = ColumnDef::new(Alias::new("id")).string().to_owned().into();
555        assert_eq!(
556            column.get_info(&DateTimeCrate::Chrono).as_str(),
557            "Column `id`: Option<String>"
558        );
559
560        let column: Column = ColumnDef::new(Alias::new("id"))
561            .string()
562            .not_null()
563            .to_owned()
564            .into();
565        assert_eq!(
566            column.get_info(&DateTimeCrate::Chrono).as_str(),
567            "Column `id`: String, not_null"
568        );
569
570        let column: Column = ColumnDef::new(Alias::new("id"))
571            .string()
572            .not_null()
573            .unique_key()
574            .to_owned()
575            .into();
576        assert_eq!(
577            column.get_info(&DateTimeCrate::Chrono).as_str(),
578            "Column `id`: String, not_null, unique"
579        );
580
581        let column: Column = ColumnDef::new(Alias::new("id"))
582            .string()
583            .not_null()
584            .unique_key()
585            .auto_increment()
586            .to_owned()
587            .into();
588        assert_eq!(
589            column.get_info(&DateTimeCrate::Chrono).as_str(),
590            "Column `id`: String, auto_increment, not_null, unique"
591        );
592
593        let column: Column = ColumnDef::new(Alias::new("date_field"))
594            .date()
595            .not_null()
596            .to_owned()
597            .into();
598        assert_eq!(
599            column.get_info(&DateTimeCrate::Chrono).as_str(),
600            "Column `date_field`: Date, not_null"
601        );
602
603        let column: Column = ColumnDef::new(Alias::new("date_field"))
604            .date()
605            .not_null()
606            .to_owned()
607            .into();
608        assert_eq!(
609            column.get_info(&DateTimeCrate::Time).as_str(),
610            "Column `date_field`: TimeDate, not_null"
611        );
612
613        let column: Column = ColumnDef::new(Alias::new("time_field"))
614            .time()
615            .not_null()
616            .to_owned()
617            .into();
618        assert_eq!(
619            column.get_info(&DateTimeCrate::Chrono).as_str(),
620            "Column `time_field`: Time, not_null"
621        );
622
623        let column: Column = ColumnDef::new(Alias::new("time_field"))
624            .time()
625            .not_null()
626            .to_owned()
627            .into();
628        assert_eq!(
629            column.get_info(&DateTimeCrate::Time).as_str(),
630            "Column `time_field`: TimeTime, not_null"
631        );
632
633        let column: Column = ColumnDef::new(Alias::new("date_time_field"))
634            .date_time()
635            .not_null()
636            .to_owned()
637            .into();
638        assert_eq!(
639            column.get_info(&DateTimeCrate::Chrono).as_str(),
640            "Column `date_time_field`: DateTime, not_null"
641        );
642
643        let column: Column = ColumnDef::new(Alias::new("date_time_field"))
644            .date_time()
645            .not_null()
646            .to_owned()
647            .into();
648        assert_eq!(
649            column.get_info(&DateTimeCrate::Time).as_str(),
650            "Column `date_time_field`: TimeDateTime, not_null"
651        );
652
653        let column: Column = ColumnDef::new(Alias::new("timestamp_field"))
654            .timestamp()
655            .not_null()
656            .to_owned()
657            .into();
658        assert_eq!(
659            column.get_info(&DateTimeCrate::Chrono).as_str(),
660            "Column `timestamp_field`: DateTimeUtc, not_null"
661        );
662
663        let column: Column = ColumnDef::new(Alias::new("timestamp_field"))
664            .timestamp()
665            .not_null()
666            .to_owned()
667            .into();
668        assert_eq!(
669            column.get_info(&DateTimeCrate::Time).as_str(),
670            "Column `timestamp_field`: TimeDateTime, not_null"
671        );
672
673        let column: Column = ColumnDef::new(Alias::new("timestamp_with_timezone_field"))
674            .timestamp_with_time_zone()
675            .not_null()
676            .to_owned()
677            .into();
678        assert_eq!(
679            column.get_info(&DateTimeCrate::Chrono).as_str(),
680            "Column `timestamp_with_timezone_field`: DateTimeWithTimeZone, not_null"
681        );
682
683        let column: Column = ColumnDef::new(Alias::new("timestamp_with_timezone_field"))
684            .timestamp_with_time_zone()
685            .not_null()
686            .to_owned()
687            .into();
688        assert_eq!(
689            column.get_info(&DateTimeCrate::Time).as_str(),
690            "Column `timestamp_with_timezone_field`: TimeDateTimeWithTimeZone, not_null"
691        );
692    }
693
694    #[test]
695    fn test_from_column_def() {
696        let column: Column = ColumnDef::new(Alias::new("id")).string().to_owned().into();
697        assert_eq!(
698            column.get_def().to_string(),
699            quote! {
700                ColumnType::String(StringLen::None).def().null()
701            }
702            .to_string()
703        );
704
705        let column: Column = ColumnDef::new(Alias::new("id"))
706            .string()
707            .not_null()
708            .to_owned()
709            .into();
710        assert!(column.not_null);
711
712        let column: Column = ColumnDef::new(Alias::new("id"))
713            .string()
714            .unique_key()
715            .not_null()
716            .to_owned()
717            .into();
718        assert!(column.unique);
719        assert!(column.not_null);
720
721        let column: Column = ColumnDef::new(Alias::new("id"))
722            .string()
723            .auto_increment()
724            .unique_key()
725            .not_null()
726            .to_owned()
727            .into();
728        assert!(column.auto_increment);
729        assert!(column.unique);
730        assert!(column.not_null);
731    }
732}