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::Vector".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::Interval(_, _)
84                | ColumnType::Cidr
85                | ColumnType::Inet
86                | ColumnType::MacAddr
87                | ColumnType::LTree => "String".to_owned(),
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) => Some(format!("custom(\"{}\")", iden.to_string())),
109            ColumnType::Binary(s) => Some(format!("Binary({s})")),
110            ColumnType::VarBinary(s) => match s {
111                StringLen::N(s) => Some(format!("VarBinary(StringLen::N({s}))")),
112                StringLen::None => Some("VarBinary(StringLen::None)".to_owned()),
113                StringLen::Max => Some("VarBinary(StringLen::Max)".to_owned()),
114            },
115            ColumnType::Blob => Some("Blob".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::Custom(s) => {
173                    let s = s.to_string();
174                    quote! { ColumnType::custom(#s) }
175                }
176                ColumnType::Enum { name, .. } => {
177                    let enum_ident = format_ident!("{}", name.to_string().to_upper_camel_case());
178                    quote! { #enum_ident::db_type() }
179                }
180                ColumnType::Array(column_type) => {
181                    let column_type = write_col_def(column_type);
182                    quote! { ColumnType::Array(RcOrArc::new(#column_type)) }
183                }
184                ColumnType::Vector(size) => match size {
185                    Some(size) => quote! { ColumnType::Vector(Some(#size)) },
186                    None => quote! { ColumnType::Vector(None) },
187                },
188                #[allow(unreachable_patterns)]
189                _ => unimplemented!(),
190            }
191        }
192        let mut col_def = write_col_def(&self.col_type);
193        col_def.extend(quote! {
194            .def()
195        });
196        if !self.not_null {
197            col_def.extend(quote! {
198                .null()
199            });
200        }
201        if self.unique {
202            col_def.extend(quote! {
203                .unique()
204            });
205        }
206        col_def
207    }
208
209    pub fn get_info(&self, date_time_crate: &DateTimeCrate) -> String {
210        let mut info = String::new();
211        let type_info = self
212            .get_rs_type(date_time_crate)
213            .to_string()
214            .replace(' ', "");
215        let col_info = self.col_info();
216        write!(
217            &mut info,
218            "Column `{}`: {}{}",
219            self.name, type_info, col_info
220        )
221        .unwrap();
222        info
223    }
224
225    fn col_info(&self) -> String {
226        let mut info = String::new();
227        if self.auto_increment {
228            write!(&mut info, ", auto_increment").unwrap();
229        }
230        if self.not_null {
231            write!(&mut info, ", not_null").unwrap();
232        }
233        if self.unique {
234            write!(&mut info, ", unique").unwrap();
235        }
236        info
237    }
238
239    pub fn get_serde_attribute(
240        &self,
241        is_primary_key: bool,
242        serde_skip_deserializing_primary_key: bool,
243        serde_skip_hidden_column: bool,
244    ) -> TokenStream {
245        if self.name.starts_with('_') && serde_skip_hidden_column {
246            quote! {
247                #[serde(skip)]
248            }
249        } else if serde_skip_deserializing_primary_key && is_primary_key {
250            quote! {
251                #[serde(skip_deserializing)]
252            }
253        } else {
254            quote! {}
255        }
256    }
257
258    pub fn get_inner_col_type(&self) -> &ColumnType {
259        match &self.col_type {
260            ColumnType::Array(inner_col_type) => inner_col_type.as_ref(),
261            _ => &self.col_type,
262        }
263    }
264}
265
266impl From<ColumnDef> for Column {
267    fn from(col_def: ColumnDef) -> Self {
268        (&col_def).into()
269    }
270}
271
272impl From<&ColumnDef> for Column {
273    fn from(col_def: &ColumnDef) -> Self {
274        let name = col_def.get_column_name();
275        let col_type = match col_def.get_column_type() {
276            Some(ty) => ty.clone(),
277            None => panic!("ColumnType should not be empty"),
278        };
279        let auto_increment = col_def
280            .get_column_spec()
281            .iter()
282            .any(|spec| matches!(spec, ColumnSpec::AutoIncrement));
283        let not_null = col_def
284            .get_column_spec()
285            .iter()
286            .any(|spec| matches!(spec, ColumnSpec::NotNull));
287        let unique = col_def
288            .get_column_spec()
289            .iter()
290            .any(|spec| matches!(spec, ColumnSpec::UniqueKey));
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}