1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
use crate::postgres::def::{ColumnInfo, Type};
use sea_query::{Alias, BlobSize, ColumnDef, ColumnType, DynIden, IntoIden, PgInterval, SeaRc};
use std::{convert::TryFrom, fmt::Write};
impl ColumnInfo {
pub fn write(&self) -> ColumnDef {
let mut col_info = self.clone();
let mut extras: Vec<String> = Vec::new();
if let Some(default) = self.default.as_ref() {
if default.0.starts_with("nextval") {
col_info = Self::convert_to_serial(col_info);
} else {
let mut string = "".to_owned();
write!(&mut string, "DEFAULT {}", default.0).unwrap();
extras.push(string);
}
}
let col_type = col_info.write_col_type();
let mut col_def = ColumnDef::new_with_type(Alias::new(self.name.as_str()), col_type);
if self.is_identity {
col_info = Self::convert_to_serial(col_info);
}
if matches!(
col_info.col_type,
Type::SmallSerial | Type::Serial | Type::BigSerial
) {
col_def.auto_increment();
}
if self.not_null.is_some() {
col_def.not_null();
}
if !extras.is_empty() {
col_def.extra(extras.join(" "));
}
col_def
}
fn convert_to_serial(mut col_info: ColumnInfo) -> ColumnInfo {
match col_info.col_type {
Type::SmallInt => {
col_info.col_type = Type::SmallSerial;
}
Type::Integer => {
col_info.col_type = Type::Serial;
}
Type::BigInt => {
col_info.col_type = Type::BigSerial;
}
_ => {}
};
col_info
}
pub fn write_col_type(&self) -> ColumnType {
fn write_type(col_type: &Type) -> ColumnType {
match col_type {
Type::SmallInt => ColumnType::SmallInteger(None),
Type::Integer => ColumnType::Integer(None),
Type::BigInt => ColumnType::BigInteger(None),
Type::Decimal(num_attr) | Type::Numeric(num_attr) => {
match (num_attr.precision, num_attr.scale) {
(None, None) => ColumnType::Decimal(None),
(precision, scale) => ColumnType::Decimal(Some((
precision.unwrap_or(0).into(),
scale.unwrap_or(0).into(),
))),
}
}
Type::Real => ColumnType::Float(None),
Type::DoublePrecision => ColumnType::Double(None),
Type::SmallSerial => ColumnType::SmallInteger(None),
Type::Serial => ColumnType::Integer(None),
Type::BigSerial => ColumnType::BigInteger(None),
Type::Money => ColumnType::Money(None),
Type::Varchar(string_attr) => {
ColumnType::String(string_attr.length.map(Into::into))
}
Type::Char(string_attr) => ColumnType::Char(string_attr.length.map(Into::into)),
Type::Text => ColumnType::Text,
Type::Bytea => ColumnType::Binary(BlobSize::Blob(None)),
Type::Timestamp(time_attr) => {
ColumnType::DateTime(time_attr.precision.map(Into::into))
}
Type::TimestampWithTimeZone(time_attr) => {
ColumnType::TimestampWithTimeZone(time_attr.precision.map(Into::into))
}
Type::Date => ColumnType::Date,
Type::Time(time_attr) => ColumnType::Time(time_attr.precision.map(Into::into)),
Type::TimeWithTimeZone(time_attr) => {
ColumnType::Time(time_attr.precision.map(Into::into))
}
Type::Interval(interval_attr) => {
let field = match &interval_attr.field {
Some(field) => PgInterval::try_from(field).ok(),
None => None,
};
let precision = interval_attr.precision.map(Into::into);
ColumnType::Interval(field, precision)
}
Type::Boolean => ColumnType::Boolean,
Type::Point => ColumnType::Custom(Alias::new("point").into_iden()),
Type::Line => ColumnType::Custom(Alias::new("line").into_iden()),
Type::Lseg => ColumnType::Custom(Alias::new("lseg").into_iden()),
Type::Box => ColumnType::Custom(Alias::new("box").into_iden()),
Type::Path => ColumnType::Custom(Alias::new("path").into_iden()),
Type::Polygon => ColumnType::Custom(Alias::new("polygon").into_iden()),
Type::Circle => ColumnType::Custom(Alias::new("circle").into_iden()),
Type::Cidr => ColumnType::Custom(Alias::new("cidr").into_iden()),
Type::Inet => ColumnType::Custom(Alias::new("inet").into_iden()),
Type::MacAddr => ColumnType::Custom(Alias::new("macaddr").into_iden()),
Type::MacAddr8 => ColumnType::Custom(Alias::new("macaddr8").into_iden()),
Type::Bit(bit_attr) => {
let mut str = String::new();
write!(str, "bit").unwrap();
if bit_attr.length.is_some() {
write!(str, "(").unwrap();
if let Some(length) = bit_attr.length {
write!(str, "{}", length).unwrap();
}
write!(str, ")").unwrap();
}
ColumnType::Custom(Alias::new(&str).into_iden())
}
Type::TsVector => ColumnType::Custom(Alias::new("tsvector").into_iden()),
Type::TsQuery => ColumnType::Custom(Alias::new("tsquery").into_iden()),
Type::Uuid => ColumnType::Uuid,
Type::Xml => ColumnType::Custom(Alias::new("xml").into_iden()),
Type::Json => ColumnType::Json,
Type::JsonBinary => ColumnType::JsonBinary,
Type::Int4Range => ColumnType::Custom(Alias::new("int4range").into_iden()),
Type::Int8Range => ColumnType::Custom(Alias::new("int8range").into_iden()),
Type::NumRange => ColumnType::Custom(Alias::new("numrange").into_iden()),
Type::TsRange => ColumnType::Custom(Alias::new("tsrange").into_iden()),
Type::TsTzRange => ColumnType::Custom(Alias::new("tstzrange").into_iden()),
Type::DateRange => ColumnType::Custom(Alias::new("daterange").into_iden()),
Type::PgLsn => ColumnType::Custom(Alias::new("pg_lsn").into_iden()),
Type::Unknown(s) => ColumnType::Custom(Alias::new(s).into_iden()),
Type::Enum(enum_def) => {
let name = Alias::new(&enum_def.typename).into_iden();
let variants: Vec<DynIden> = enum_def
.values
.iter()
.map(|variant| Alias::new(variant).into_iden())
.collect();
ColumnType::Enum { name, variants }
}
Type::Array(array_def) => ColumnType::Array(SeaRc::new(Box::new(write_type(
array_def.col_type.as_ref().expect("Array type not defined"),
)))),
}
}
write_type(&self.col_type)
}
}